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
));
100 memset((*psattrp
)->psa_subcpuprefs
, 0xff /* CPU_SUBTYPE_ANY */,
101 sizeof((*psattrp
)->psa_subcpuprefs
));
103 /* Default is no port actions to take */
104 (*psattrp
)->psa_ports
= NULL
;
107 * The default value of this attribute shall be an no
108 * process control on resource starvation
110 (*psattrp
)->psa_pcontrol
= 0;
113 * Initializing the alignment paddings.
116 (*psattrp
)->short_padding
= 0;
117 (*psattrp
)->flags_padding
= 0;
119 /* Default is no new apptype requested */
120 (*psattrp
)->psa_apptype
= POSIX_SPAWN_PROCESS_TYPE_DEFAULT
;
123 (*psattrp
)->psa_jetsam_flags
= 0;
124 (*psattrp
)->psa_priority
= -1;
125 (*psattrp
)->psa_memlimit_active
= -1;
126 (*psattrp
)->psa_memlimit_inactive
= -1;
128 /* Default is no thread limit */
129 (*psattrp
)->psa_thread_limit
= 0;
131 /* Default is no CPU usage monitor active. */
132 (*psattrp
)->psa_cpumonitor_percent
= 0;
133 (*psattrp
)->psa_cpumonitor_interval
= 0;
135 /* Default is no MAC policy extensions. */
136 (*psattrp
)->psa_mac_extensions
= NULL
;
138 /* Default is to inherit parent's coalition(s) */
139 (*psattrp
)->psa_coalition_info
= NULL
;
141 (*psattrp
)->psa_persona_info
= NULL
;
143 (*psattrp
)->psa_posix_cred_info
= NULL
;
146 * old coalition field
147 * For backwards compatibility reasons, we set this to 1
148 * which is the first valid coalition id. This will allow
149 * newer user space code to properly spawn processes on
151 * (they will just all end up in the same coalition).
153 (*psattrp
)->psa_reserved
= 1;
155 /* Default is no new clamp */
156 (*psattrp
)->psa_qos_clamp
= POSIX_SPAWN_PROC_CLAMP_NONE
;
158 /* Default is no change to role */
159 (*psattrp
)->psa_darwin_role
= POSIX_SPAWN_DARWIN_ROLE_NONE
;
161 (*psattrp
)->psa_max_addr
= 0;
163 (*psattrp
)->psa_no_smt
= false;
164 (*psattrp
)->psa_tecs
= false;
166 /* Default is no subsystem root path */
167 (*psattrp
)->psa_subsystem_root_path
= NULL
;
169 /* Default is no platform given */
170 (*psattrp
)->psa_platform
= 0;
172 /* Default is no option */
173 (*psattrp
)->psa_options
= PSA_OPTION_NONE
;
181 * posix_spawnattr_destroy
183 * Description: Destroy a spawn attributes object that was previously
184 * initialized via posix_spawnattr_init() by freeing any
185 * memory associated with it and setting it to an invalid value.
187 * Parameters: attr The spawn attributes object to be
192 * Notes: The destroyed spawn attribute results in the void * pointer
193 * being set to NULL; subsequent use without reinitialization
194 * will result in explicit program failure (rather than merely
195 * "undefined behaviour").
197 * NOTIMP: Allowed failures (checking NOT required):
198 * EINVAL The value specified by attr is invalid.
200 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
201 static int posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*);
202 static int posix_spawn_destroypersona_info_np(posix_spawnattr_t
*);
203 static int posix_spawn_destroyposix_cred_info_np(posix_spawnattr_t
*);
204 static int posix_spawn_destroymacpolicy_info_np(posix_spawnattr_t
*);
205 static int posix_spawn_destroysubsystem_root_path_np(posix_spawnattr_t
*);
208 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
210 _posix_spawnattr_t psattr
;
212 if (attr
== NULL
|| *attr
== NULL
) {
216 psattr
= *(_posix_spawnattr_t
*)attr
;
217 posix_spawn_destroyportactions_np(attr
);
218 posix_spawn_destroycoalition_info_np(attr
);
219 posix_spawn_destroypersona_info_np(attr
);
220 posix_spawn_destroyposix_cred_info_np(attr
);
221 posix_spawn_destroymacpolicy_info_np(attr
);
222 posix_spawn_destroysubsystem_root_path_np(attr
);
232 * posix_spawnattr_setflags
234 * Description: Set the spawn flags attribute for the spawn attribute object
235 * referred to by 'attr'.
237 * Parameters: attr The spawn attributes object whose flags
239 * flags The flags value to set
243 * NOTIMP: Allowed failures (checking NOT required):
244 * EINVAL The value specified by attr is invalid.
245 * EINVAL The value of the attribute being set is not valid.
248 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
250 _posix_spawnattr_t psattr
;
252 if (attr
== NULL
|| *attr
== NULL
) {
256 psattr
= *(_posix_spawnattr_t
*)attr
;
257 psattr
->psa_flags
= flags
;
264 * posix_spawnattr_getflags
266 * Description: Retrieve the spawn attributes flag for the spawn attributes
267 * object referenced by 'attr' and place them in the memory
268 * location referenced by 'flagsp'
270 * Parameters: attr The spawn attributes object whose flags
271 * are to be retrieved
272 * flagsp A pointer to a short value to receive
278 * *flagps (modified) The flags value from the spawn
281 * NOTIMP: Allowed failures (checking NOT required):
282 * EINVAL The value specified by attr is invalid.
283 * EINVAL The value of the attribute being set is not valid.
286 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
287 short * __restrict flagsp
)
289 _posix_spawnattr_t psattr
;
291 if (attr
== NULL
|| *attr
== NULL
) {
295 psattr
= *(_posix_spawnattr_t
*)attr
;
296 *flagsp
= psattr
->psa_flags
;
303 * posix_spawnattr_getsigdefault
305 * Description: Retrieve the set of signals to be set to default according to
306 * the spawn attribute value referenced by 'attr' and place the
307 * result into the memory containing the sigset_t referenced by
310 * Parameters: attr The spawn attributes object whose
311 * signal set for default signals is to
313 * sigdefault A pointer to the sigset_t to receive
319 * *sigdefault (modified) The signal set of signals to default
320 * from the spawn attributes object
323 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
324 sigset_t
* __restrict sigdefault
)
326 _posix_spawnattr_t psattr
;
328 if (attr
== NULL
|| *attr
== NULL
) {
332 psattr
= *(_posix_spawnattr_t
*)attr
;
333 *sigdefault
= psattr
->psa_sigdefault
;
340 * posix_spawnattr_getpgroup
342 * Description: Obtain the value of the spawn process group attribute from the
343 * spawn attributes object referenced by 'attr' and place the
344 * results in the memory location referenced by 'pgroup'
346 * Parameters: attr The spawn attributes object whose
347 * process group information is to be
349 * pgroup A pointer to the pid_t to receive the
355 * *pgroup (modified) The process group information from the
356 * spawn attributes object
359 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
360 pid_t
* __restrict pgroup
)
362 _posix_spawnattr_t psattr
;
364 if (attr
== NULL
|| *attr
== NULL
) {
368 psattr
= *(_posix_spawnattr_t
*)attr
;
369 *pgroup
= psattr
->psa_pgroup
;
376 * posix_spawnattr_getsigmask
378 * Description: Obtain the value of the spawn signal mask attribute from the
379 * spawn attributes object referenced by 'attr' and place the
380 * result into the memory containing the sigset_t referenced by
383 * Parameters: attr The spawn attributes object whose
384 * signal set for masked signals is to
386 * sigmask A pointer to the sigset_t to receive
392 * *sigmask (modified) The signal set of signals to mask
393 * from the spawn attributes object
396 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
397 sigset_t
* __restrict sigmask
)
399 _posix_spawnattr_t psattr
;
401 if (attr
== NULL
|| *attr
== NULL
) {
405 psattr
= *(_posix_spawnattr_t
*)attr
;
406 *sigmask
= psattr
->psa_sigmask
;
412 * posix_spawnattr_getbinpref_np
414 * Description: Obtain the value of the spawn binary preferences attribute from
415 * the spawn attributes object referenced by 'attr' and place the
416 * result into the memory referenced by 'pref'.
418 * Parameters: attr The spawn attributes object whose
419 * binary preferences are to be retrieved
420 * count The size of the cpu_type_t array
421 * pref An array of cpu types
422 * ocount The actual number copied
424 * Returns: 0 No binary preferences found
425 * > 0 The number of cpu types (less than
426 * count) copied over from 'attr'.
429 * *pref (modified) The binary preferences array
430 * from the spawn attributes object
433 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
434 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
436 _posix_spawnattr_t psattr
;
439 if (attr
== NULL
|| *attr
== NULL
|| pref
== NULL
) {
443 psattr
= *(_posix_spawnattr_t
*)attr
;
444 for (i
= 0; i
< count
&& i
< NBINPREFS
; i
++) {
445 pref
[i
] = psattr
->psa_binprefs
[i
];
455 * posix_spawnattr_getarchpref_np
457 * Description: Obtain the value of the spawn binary preferences attribute from
458 * the spawn attributes object referenced by 'attr' and place the
459 * result into the memory referenced by 'pref' and 'subpref'.
461 * Parameters: attr The spawn attributes object whose
462 * binary preferences are to be retrieved
463 * count The size of the cpu_type_t array
464 * pref An array of cpu types
465 * subpref An array of subcpu types
466 * ocount The actual number copied
468 * Returns: 0 No cpu/subcpu preferences found
469 * > 0 The number of types (less than
470 * count) copied over from 'attr'.
473 * *pref (modified) The cpu preferences array
474 * from the spawn attributes object
475 * *subpref (modified) The subcpu preferences array
476 * from the spawn attributes object
479 posix_spawnattr_getarchpref_np(const posix_spawnattr_t
* __restrict attr
,
480 size_t count
, cpu_type_t
*pref
, cpu_subtype_t
*subpref
, size_t * __restrict ocount
)
482 _posix_spawnattr_t psattr
;
485 if (attr
== NULL
|| *attr
== NULL
|| pref
== NULL
|| subpref
== NULL
) {
489 psattr
= *(_posix_spawnattr_t
*)attr
;
490 for (i
= 0; i
< count
&& i
< NBINPREFS
; i
++) {
491 pref
[i
] = psattr
->psa_binprefs
[i
];
492 subpref
[i
] = psattr
->psa_subcpuprefs
[i
];
503 * posix_spawnattr_getpcontrol_np
505 * Description: Retrieve the process control property set default according to
506 * the spawn attribute value referenced by 'attr' and place the
507 * result into the memory containing the control referenced by
510 * Parameters: attr The spawn attributes object whose
511 * signal set for default signals is to
513 * pcontrol A pointer to an int to receive
514 * the process control info
519 * *pcontrol (modified) The signal set of signals to default
520 * from the spawn attributes object
523 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
524 int * __restrict pcontrol
)
526 _posix_spawnattr_t psattr
;
528 if (attr
== NULL
|| *attr
== NULL
) {
532 psattr
= *(_posix_spawnattr_t
*)attr
;
533 *pcontrol
= psattr
->psa_pcontrol
;
539 * posix_spawnattr_getprocesstype_np
541 * Description: Retrieve the process specific behaviors and app launch types
542 * spawn attribute value referenced by 'attr' and place the
543 * result into the memory containing the control referenced by
546 * Parameters: attr The spawn attributes object whose
547 * signal set for default signals is to
549 * proctype A pointer to an int to receive
550 * the process type info
555 * *proctype (modified) The process type set to value
556 * from the spawn attributes object
559 posix_spawnattr_getprocesstype_np(const posix_spawnattr_t
* __restrict attr
,
560 int * __restrict proctype
)
562 _posix_spawnattr_t psattr
;
564 if (attr
== NULL
|| *attr
== NULL
) {
568 psattr
= *(_posix_spawnattr_t
*)attr
;
569 *proctype
= psattr
->psa_apptype
;
574 * posix_spawnattr_setsigdefault
576 * Description: Set the set of signals to be set to default for the spawn
577 * attribute value referenced by 'attr' from the memory
578 * containing the sigset_t referenced by 'sigdefault'
580 * Parameters: attr The spawn attributes object whose
581 * signal set for default signals is to
583 * sigdefault A pointer to the sigset_t from which to
584 * obtain the signal set
589 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
590 const sigset_t
* __restrict sigdefault
)
592 _posix_spawnattr_t psattr
;
594 if (attr
== NULL
|| *attr
== NULL
) {
598 psattr
= *(_posix_spawnattr_t
*)attr
;
599 psattr
->psa_sigdefault
= *sigdefault
;
606 * posix_spawnattr_setpgroup
608 * Description: Set the value of the spawn process group attribute for the
609 * spawn attributes object referenced by 'attr' from the value
612 * Parameters: attr The spawn attributes object for which
613 * the process group information is to be
615 * pgroup The process group to set
620 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
622 _posix_spawnattr_t psattr
;
624 if (attr
== NULL
|| *attr
== NULL
) {
628 psattr
= *(_posix_spawnattr_t
*)attr
;
629 psattr
->psa_pgroup
= pgroup
;
636 * posix_spawnattr_setsigmask
638 * Description: Set the set of signals to be masked for the spawn attribute
639 * value referenced by 'attr' from the memory containing the
640 * sigset_t referenced by 'sigmask'
642 * Parameters: attr The spawn attributes object whose
643 * signal set for masked signals is to
645 * sigmask A pointer to the sigset_t from which to
646 * obtain the signal set
651 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
652 const sigset_t
* __restrict sigmask
)
654 _posix_spawnattr_t psattr
;
656 if (attr
== NULL
|| *attr
== NULL
) {
660 psattr
= *(_posix_spawnattr_t
*)attr
;
661 psattr
->psa_sigmask
= *sigmask
;
668 * posix_spawnattr_setbinpref_np
670 * Description: Set the universal binary preferences for the spawn attribute
671 * value referenced by 'attr' from the memory containing the
672 * cpu_type_t array referenced by 'pref', size of 'count'
674 * Parameters: attr The spawn attributes object whose
675 * binary preferences are to be set
676 * count Size of the array pointed to by 'pref'
677 * pref cpu_type_t array of binary preferences
678 * ocount The actual number copied
680 * Returns: 0 No preferences copied
681 * > 0 Number of preferences copied
683 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
684 * If the caller provides more preferences than this limit, they
685 * will be ignored, as reflected in the return value.
688 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
689 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
691 _posix_spawnattr_t psattr
;
694 if (attr
== NULL
|| *attr
== NULL
|| pref
== NULL
) {
698 psattr
= *(_posix_spawnattr_t
*)attr
;
699 for (i
= 0; i
< count
&& i
< NBINPREFS
; i
++) {
700 psattr
->psa_binprefs
[i
] = pref
[i
];
701 psattr
->psa_subcpuprefs
[i
] = CPU_SUBTYPE_ANY
;
704 /* return number of binprefs copied over */
709 for (; i
< NBINPREFS
; i
++) {
710 psattr
->psa_binprefs
[i
] = 0;
711 psattr
->psa_subcpuprefs
[i
] = CPU_SUBTYPE_ANY
;
718 * posix_spawnattr_setarchpref_np
720 * Description: Set the universal binary preferences for the spawn attribute
721 * value referenced by 'attr' from the memory containing the
722 * cpu_type_t array referenced by 'pref', the cpu_subtype_t array
723 * referenced by 'subpref' and size of 'count'
725 * Parameters: attr The spawn attributes object whose
726 * binary preferences are to be set
727 * count Size of the array pointed to by 'pref'
728 * pref cpu_type_t array of cpu binary preferences
729 * subpref cpu_subtype_t array of subcpu binary preferences
730 * ocount The actual number copied
732 * Returns: 0 No preferences copied
733 * > 0 Number of preferences copied
735 * Note: The posix_spawnattr_t currently only holds four
736 * cpu_type_t/cpu_subtype_t pairs.
737 * If the caller provides more preferences than this limit, they
738 * will be ignored, as reflected in the return value.
741 posix_spawnattr_setarchpref_np(posix_spawnattr_t
* __restrict attr
,
742 size_t count
, cpu_type_t
*pref
, cpu_subtype_t
*subpref
,
743 size_t * __restrict ocount
)
745 _posix_spawnattr_t psattr
;
748 if (attr
== NULL
|| *attr
== NULL
|| pref
== NULL
|| subpref
== NULL
) {
752 psattr
= *(_posix_spawnattr_t
*)attr
;
753 for (i
= 0; i
< count
&& i
< NBINPREFS
; i
++) {
754 psattr
->psa_binprefs
[i
] = pref
[i
];
755 psattr
->psa_subcpuprefs
[i
] = subpref
[i
];
758 /* return number of binprefs copied over */
763 for (; i
< NBINPREFS
; i
++) {
764 psattr
->psa_binprefs
[i
] = 0;
765 psattr
->psa_subcpuprefs
[i
] = CPU_SUBTYPE_ANY
;
772 * posix_spawnattr_setpcontrol_np
774 * Description: Set the process control property according to
775 * attribute value referenced by 'attr' from the memory
776 * containing the int value 'pcontrol'
778 * Parameters: attr The spawn attributes object whose
779 * signal set for default signals is to
781 * pcontrol An int value of the process control info
786 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
789 _posix_spawnattr_t psattr
;
791 if (attr
== NULL
|| *attr
== NULL
) {
795 psattr
= *(_posix_spawnattr_t
*)attr
;
796 psattr
->psa_pcontrol
= pcontrol
;
803 * posix_spawnattr_setprocesstype_np
805 * Description: Set the process specific behaviors and app launch type
806 * attribute value referenced by 'attr' from the memory
807 * containing the int value 'proctype'
809 * Parameters: attr The spawn attributes object whose
810 * signal set for default signals is to
812 * proctype An int value of the process type info
817 posix_spawnattr_setprocesstype_np(posix_spawnattr_t
* __restrict attr
,
820 _posix_spawnattr_t psattr
;
822 if (attr
== NULL
|| *attr
== NULL
) {
826 psattr
= *(_posix_spawnattr_t
*)attr
;
827 psattr
->psa_apptype
= proctype
;
833 * posix_spawn_createportactions_np
834 * Description: create a new posix_spawn_port_actions struct and link
835 * it into the posix_spawnattr.
838 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
840 _posix_spawnattr_t psattr
;
841 _posix_spawn_port_actions_t acts
;
843 if (attr
== NULL
|| *attr
== NULL
) {
847 psattr
= *(_posix_spawnattr_t
*)attr
;
848 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
853 acts
->pspa_alloc
= 2;
854 acts
->pspa_count
= 0;
856 psattr
->psa_ports
= acts
;
861 * posix_spawn_growportactions_np
862 * Description: Enlarge the size of portactions if necessary
865 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
867 _posix_spawnattr_t psattr
;
868 _posix_spawn_port_actions_t acts
;
870 if (attr
== NULL
|| *attr
== NULL
) {
874 psattr
= *(_posix_spawnattr_t
*)attr
;
875 acts
= psattr
->psa_ports
;
880 /* Double number of port actions allocated for */
882 if (os_mul_overflow(acts
->pspa_alloc
, 2, &newnum
)) {
885 size_t newsize
= PS_PORT_ACTIONS_SIZE(newnum
);
890 acts
= realloc(acts
, newsize
);
895 acts
->pspa_alloc
= newnum
;
896 psattr
->psa_ports
= acts
;
901 * posix_spawn_destroyportactions_np
902 * Description: clean up portactions struct in posix_spawnattr_t attr
905 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
907 _posix_spawnattr_t psattr
;
908 _posix_spawn_port_actions_t acts
;
910 if (attr
== NULL
|| *attr
== NULL
) {
914 psattr
= *(_posix_spawnattr_t
*)attr
;
915 acts
= psattr
->psa_ports
;
925 * posix_spawn_destroycoalition_info_np
926 * Description: clean up coalition_info struct in posix_spawnattr_t attr
929 posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*attr
)
931 _posix_spawnattr_t psattr
;
932 struct _posix_spawn_coalition_info
*coal_info
;
934 if (attr
== NULL
|| *attr
== NULL
) {
938 psattr
= *(_posix_spawnattr_t
*)attr
;
939 coal_info
= psattr
->psa_coalition_info
;
940 if (coal_info
== NULL
) {
944 psattr
->psa_coalition_info
= NULL
;
950 * posix_spawn_destroypersona_info_np
951 * Description: clean up persona_info struct in posix_spawnattr_t attr
954 posix_spawn_destroypersona_info_np(posix_spawnattr_t
*attr
)
956 _posix_spawnattr_t psattr
;
957 struct _posix_spawn_persona_info
*persona
;
959 if (attr
== NULL
|| *attr
== NULL
) {
963 psattr
= *(_posix_spawnattr_t
*)attr
;
964 persona
= psattr
->psa_persona_info
;
965 if (persona
== NULL
) {
969 psattr
->psa_persona_info
= NULL
;
975 * posix_spawn_destroyposix_cred_info_np
976 * Description: clean up posix_cred_info struct in posix_spawnattr_t attr
979 posix_spawn_destroyposix_cred_info_np(posix_spawnattr_t
*attr
)
981 _posix_spawnattr_t psattr
;
982 struct _posix_spawn_posix_cred_info
*pspci
;
984 if (attr
== NULL
|| *attr
== NULL
) {
988 psattr
= *(_posix_spawnattr_t
*)attr
;
989 pspci
= psattr
->psa_posix_cred_info
;
994 psattr
->psa_posix_cred_info
= NULL
;
1000 * posix_spawn_set_subsystem_root_path
1001 * Description: Set path as the subsystem root path for attr; clears if NULL
1004 posix_spawnattr_set_subsystem_root_path_np(posix_spawnattr_t
*attr
, char *path
)
1006 _posix_spawnattr_t psattr
;
1011 if (attr
== NULL
|| *attr
== NULL
) {
1015 psattr
= *(_posix_spawnattr_t
*)attr
;
1018 buf
= malloc(MAXPATHLEN
);
1024 bytes
= strlcpy(buf
, path
, MAXPATHLEN
);
1026 if (bytes
>= MAXPATHLEN
) {
1028 return ENAMETOOLONG
;
1032 old_buf
= psattr
->psa_subsystem_root_path
;
1033 psattr
->psa_subsystem_root_path
= buf
;
1041 * posix_spawn_destroy_subsystem_root_path_np
1042 * Description: clean up subsystem_root_path string in posix_spawnattr_t attr
1045 posix_spawn_destroysubsystem_root_path_np(posix_spawnattr_t
*attr
)
1047 _posix_spawnattr_t psattr
;
1048 char * subsystem_root_path
;
1050 if (attr
== NULL
|| *attr
== NULL
) {
1054 psattr
= *(_posix_spawnattr_t
*)attr
;
1055 subsystem_root_path
= psattr
->psa_subsystem_root_path
;
1057 if (subsystem_root_path
== NULL
) {
1061 psattr
->psa_subsystem_root_path
= NULL
;
1062 free(subsystem_root_path
);
1067 * posix_spawnattr_set_platform_np
1068 * Description: sets the platform in posix_spawnattr_t attr
1070 * To be implemented.
1073 posix_spawnattr_set_platform_np(posix_spawnattr_t
*attr
, int platform
, uint32_t flags
)
1075 _posix_spawnattr_t psattr
;
1077 if (attr
== NULL
|| *attr
== NULL
) {
1081 psattr
= *(_posix_spawnattr_t
*)attr
;
1082 psattr
->psa_platform
= platform
;
1089 * posix_spawnattr_disable_ptr_auth_a_keys_np
1090 * Description: Set flag to disable A keys for Ptr Auth
1093 posix_spawnattr_disable_ptr_auth_a_keys_np(posix_spawnattr_t
*attr
, uint32_t flags
)
1095 _posix_spawnattr_t psattr
;
1097 if (attr
== NULL
|| *attr
== NULL
) {
1101 psattr
= *(_posix_spawnattr_t
*)attr
;
1103 psattr
->psa_options
|= PSA_OPTION_PLUGIN_HOST_DISABLE_A_KEYS
;
1109 * posix_spawn_appendportaction_np
1110 * Description: append a port action, grow the array if necessary
1113 posix_spawn_appendportaction_np(posix_spawnattr_t
*attr
, _ps_port_action_t
*act
)
1115 _posix_spawnattr_t psattr
;
1116 _posix_spawn_port_actions_t acts
;
1118 if (attr
== NULL
|| *attr
== NULL
|| act
== NULL
) {
1122 psattr
= *(_posix_spawnattr_t
*)attr
;
1123 acts
= psattr
->psa_ports
;
1125 // Have any port actions been created yet?
1127 int err
= posix_spawn_createportactions_np(attr
);
1131 acts
= psattr
->psa_ports
;
1134 // Is there enough room?
1135 if (acts
->pspa_alloc
== acts
->pspa_count
) {
1136 int err
= posix_spawn_growportactions_np(attr
);
1140 acts
= psattr
->psa_ports
;
1143 // Add this action to next spot in array
1144 acts
->pspa_actions
[acts
->pspa_count
] = *act
;
1151 * posix_spawnattr_setspecialport_np
1153 * Description: Set a new value for a mach special port in the spawned task.
1155 * Parameters: attr The spawn attributes object for the
1157 * new_port The new value for the special port
1158 * which The particular port to be set
1159 * (see task_set_special_port for details)
1161 * Returns: 0 Success
1162 * ENOMEM Couldn't allocate memory
1165 posix_spawnattr_setspecialport_np(
1166 posix_spawnattr_t
*attr
,
1167 mach_port_t new_port
,
1170 _ps_port_action_t action
= {
1171 .port_type
= PSPA_SPECIAL
,
1172 .new_port
= new_port
,
1175 return posix_spawn_appendportaction_np(attr
, &action
);
1179 * posix_spawnattr_setsuidcredport_np
1181 * Description: Set an suid cred port to be used to execute with a different UID.
1183 * Parameters: attr The spawn attributes object for the
1185 * port The suid cred port
1187 * Returns: 0 Success
1190 posix_spawnattr_setsuidcredport_np(posix_spawnattr_t
*attr
, mach_port_t port
)
1192 _ps_port_action_t action
= {
1193 .port_type
= PSPA_SUID_CRED
,
1196 return posix_spawn_appendportaction_np(attr
, &action
);
1200 * posix_spawnattr_setexceptionports_np
1202 * Description: Set a new port for a set of exception ports in the spawned task.
1204 * Parameters: attr The spawn attributes object for the
1206 * mask A bitfield indicating which exceptions
1207 * to associate the port with
1208 * new_port The new value for the exception port
1209 * behavior The default behavior for the port
1210 * flavor The default flavor for the port
1211 * (see task_set_exception_ports)
1213 * Returns: 0 Success
1216 posix_spawnattr_setexceptionports_np(
1217 posix_spawnattr_t
*attr
,
1218 exception_mask_t mask
,
1219 mach_port_t new_port
,
1220 exception_behavior_t behavior
,
1221 thread_state_flavor_t flavor
)
1223 _ps_port_action_t action
= {
1224 .port_type
= PSPA_EXCEPTION
,
1226 .new_port
= new_port
,
1227 .behavior
= behavior
,
1230 return posix_spawn_appendportaction_np(attr
, &action
);
1234 * posix_spawnattr_setauditsessionport_np
1236 * Description: Set the audit session port rights attribute in the spawned task.
1237 * This is used to securely set the audit session information for
1240 * Parameters: attr The spawn attributes object for the
1242 * au_sessionport The audit session send port right
1244 * Returns: 0 Success
1247 posix_spawnattr_setauditsessionport_np(
1248 posix_spawnattr_t
*attr
,
1249 mach_port_t au_sessionport
)
1251 _ps_port_action_t action
= {
1252 .port_type
= PSPA_AU_SESSION
,
1253 .new_port
= au_sessionport
,
1255 return posix_spawn_appendportaction_np(attr
, &action
);
1260 * posix_spawn_file_actions_init
1262 * Description: Initialize a spawn file actions object attr with default values
1264 * Parameters: file_actions The spawn file actions object to be
1267 * Returns: 0 Success
1268 * ENOMEM Insufficient memory exists to
1269 * initialize the spawn file actions
1272 * Note: As an implementation detail, the externally visibily type
1273 * posix_spawn_file_actions_t is defined to be a void *, and
1274 * initialization involves allocation of a memory object.
1275 * Subsequent changes to the spawn file actions may result in
1276 * reallocation under the covers.
1278 * Reinitialization of an already initialized spawn file actions
1279 * object will result in memory being leaked. Because spawn
1280 * file actions are not required to be used in conjunction with a
1281 * static initializer, there is no way to distinguish a spawn
1282 * file actions with stack garbage from one that's been
1283 * initialized. This is arguably an API design error.
1286 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
1288 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1291 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
1294 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
1295 (*psactsp
)->psfa_act_count
= 0;
1303 * posix_spawn_file_actions_destroy
1305 * Description: Destroy a spawn file actions object that was previously
1306 * initialized via posix_spawn_file_actions_init() by freeing any
1307 * memory associated with it and setting it to an invalid value.
1309 * Parameters: attr The spawn file actions object to be
1312 * Returns: 0 Success
1314 * Notes: The destroyed spawn file actions results in the void * pointer
1315 * being set to NULL; subsequent use without reinitialization
1316 * will result in explicit program failure (rather than merely
1317 * "undefined behaviour").
1319 * NOTIMP: Allowed failures (checking NOT required):
1320 * EINVAL The value specified by file_actions is invalid.
1323 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
1325 _posix_spawn_file_actions_t psacts
;
1327 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1331 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
1333 *file_actions
= NULL
;
1340 * _posix_spawn_file_actions_grow
1342 * Description: Grow the available list of file actions associated with the
1343 * pointer to the structure provided; replace the contents of the
1344 * pointer as a side effect.
1346 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
1349 * Returns: 0 Success
1350 * ENOMEM Insufficient memory for operation
1352 * Notes: This code is common to all posix_spawn_file_actions_*()
1353 * functions, since we use a naieve data structure implementation
1354 * at present. Future optimization will likely change this.
1357 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
1360 if (os_mul_overflow((*psactsp
)->psfa_act_alloc
, 2, &newnum
)) {
1364 size_t newsize
= PSF_ACTIONS_SIZE(newnum
);
1370 * XXX may want to impose an administrative limit here; POSIX does
1371 * XXX not provide for an administrative error return in this case,
1372 * XXX so it's probably acceptable to just fail catastrophically
1373 * XXX instead of implementing one.
1375 _posix_spawn_file_actions_t new_psacts
;
1376 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), newsize
)) == NULL
) {
1379 new_psacts
->psfa_act_alloc
= newnum
;
1380 *psactsp
= new_psacts
;
1387 * posix_spawn_file_actions_addopen
1389 * Description: Add an open action to the object referenced by 'file_actions'
1390 * that will cause the file named by 'path' to be attempted to be
1391 * opened with flags 'oflag' and mode 'mode', and, if successful,
1392 * return as descriptor 'filedes' to the spawned process.
1394 * Parameters: file_actions File action object to augment
1395 * filedes fd that open is to use
1396 * path path to file to open
1397 * oflag open file flags
1398 * mode open file mode
1400 * Returns: 0 Success
1401 * EBADF The value specified by fildes is
1402 * negative or greater than or equal to
1404 * ENOMEM Insufficient memory exists to add to
1405 * the spawn file actions object.
1407 * NOTIMP: Allowed failures (checking NOT required):
1408 * EINVAL The value specified by file_actions is invalid.
1411 posix_spawn_file_actions_addopen(
1412 posix_spawn_file_actions_t
* __restrict file_actions
,
1413 int filedes
, const char * __restrict path
, int oflag
,
1416 _posix_spawn_file_actions_t
*psactsp
;
1417 _psfa_action_t
*psfileact
;
1419 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1423 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1424 /* Range check; required by POSIX */
1425 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
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_OPEN
;
1443 psfileact
->psfaa_filedes
= filedes
;
1444 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1445 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1446 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1453 * posix_spawn_file_actions_addclose
1455 * Description: Add a close action to the object referenced by 'file_actions'
1456 * that will cause the file referenced by 'filedes' to be
1457 * attempted to be closed in the spawned process.
1459 * Parameters: file_actions File action object to augment
1460 * filedes fd to close
1462 * Returns: 0 Success
1463 * EBADF The value specified by fildes is
1464 * negative or greater than or equal to
1466 * ENOMEM Insufficient memory exists to add to
1467 * the spawn file actions object.
1469 * NOTIMP: Allowed failures (checking NOT required):
1470 * EINVAL The value specified by file_actions is invalid.
1473 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1476 _posix_spawn_file_actions_t
*psactsp
;
1477 _psfa_action_t
*psfileact
;
1479 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1483 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1484 /* Range check; required by POSIX */
1485 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1489 /* If we do not have enough slots, grow the structure */
1490 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1491 /* need to grow file actions structure */
1492 if (_posix_spawn_file_actions_grow(psactsp
)) {
1498 * Allocate next available slot and fill it out
1500 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1502 psfileact
->psfaa_type
= PSFA_CLOSE
;
1503 psfileact
->psfaa_filedes
= filedes
;
1510 * posix_spawn_file_actions_adddup2
1512 * Description: Add a dup2 action to the object referenced by 'file_actions'
1513 * that will cause the file referenced by 'filedes' to be
1514 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1517 * Parameters: file_actions File action object to augment
1518 * filedes fd to dup2
1519 * newfiledes fd to dup2 it to
1521 * Returns: 0 Success
1522 * EBADF The value specified by either fildes
1523 * or by newfiledes is negative or greater
1524 * than or equal to {OPEN_MAX}.
1525 * ENOMEM Insufficient memory exists to add to
1526 * the spawn file actions object.
1528 * NOTIMP: Allowed failures (checking NOT required):
1529 * EINVAL The value specified by file_actions is invalid.
1532 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1533 int filedes
, int newfiledes
)
1535 _posix_spawn_file_actions_t
*psactsp
;
1536 _psfa_action_t
*psfileact
;
1538 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1542 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1543 /* Range check; required by POSIX */
1544 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1545 newfiledes
< 0 || newfiledes
>= OPEN_MAX
) {
1549 /* If we do not have enough slots, grow the structure */
1550 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1551 /* need to grow file actions structure */
1552 if (_posix_spawn_file_actions_grow(psactsp
)) {
1558 * Allocate next available slot and fill it out
1560 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1562 psfileact
->psfaa_type
= PSFA_DUP2
;
1563 psfileact
->psfaa_filedes
= filedes
;
1564 psfileact
->psfaa_dup2args
.psfad_newfiledes
= newfiledes
;
1570 * posix_spawn_file_actions_add_fileportdup2_np
1572 * Description: Add a dup2 action to the object referenced by 'file_actions'
1573 * that will cause the file referenced by 'fileport' to be
1574 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1577 * Parameters: file_actions File action object to augment
1578 * filedes fileport to dup2
1579 * newfiledes fd to dup2 it to
1581 * Returns: 0 Success
1582 * EBADF fileport isn't a valid port, or the
1583 * value specified by newfiledes is
1584 * negative or greater than or equal to
1586 * ENOMEM Insufficient memory exists to add to
1587 * the spawn file actions object.
1589 * NOTIMP: Allowed failures (checking NOT required):
1590 * EINVAL The value specified by file_actions is invalid.
1593 posix_spawn_file_actions_add_fileportdup2_np(
1594 posix_spawn_file_actions_t
*file_actions
,
1595 mach_port_t fileport
, int newfiledes
)
1597 _posix_spawn_file_actions_t
*psactsp
;
1598 _psfa_action_t
*psfileact
;
1600 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1604 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1605 /* Range check; required by POSIX */
1606 if (!MACH_PORT_VALID(fileport
) ||
1607 newfiledes
< 0 || newfiledes
>= OPEN_MAX
) {
1611 /* If we do not have enough slots, grow the structure */
1612 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1613 /* need to grow file actions structure */
1614 if (_posix_spawn_file_actions_grow(psactsp
)) {
1620 * Allocate next available slot and fill it out
1622 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1624 psfileact
->psfaa_type
= PSFA_FILEPORT_DUP2
;
1625 psfileact
->psfaa_fileport
= fileport
;
1626 psfileact
->psfaa_dup2args
.psfad_newfiledes
= newfiledes
;
1632 * posix_spawn_file_actions_addinherit_np
1634 * Description: Add the "inherit" action to the object referenced by
1635 * 'file_actions' that will cause the file referenced by
1636 * 'filedes' to continue to be available in the spawned
1637 * process via the same descriptor.
1639 * Inheritance is the normal default behaviour for
1640 * file descriptors across exec and spawn; but if the
1641 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1642 * default is reversed for the purposes of the spawn
1643 * invocation. Any pre-existing descriptors that
1644 * need to be made available to the spawned process can
1645 * be marked explicitly as 'inherit' via this interface.
1646 * Otherwise they will be automatically closed.
1648 * Note that any descriptors created via the other file
1649 * actions interfaces are automatically marked as 'inherit'.
1651 * Parameters: file_actions File action object to augment
1652 * filedes fd to inherit.
1654 * Returns: 0 Success
1655 * EBADF The value specified by fildes is
1656 * negative or greater than or equal to
1658 * ENOMEM Insufficient memory exists to add to
1659 * the spawn file actions object.
1661 * NOTIMP: Allowed failures (checking NOT required):
1662 * EINVAL The value specified by file_actions is invalid.
1665 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1668 _posix_spawn_file_actions_t
*psactsp
;
1669 _psfa_action_t
*psfileact
;
1671 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1675 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1676 /* Range check; required by POSIX */
1677 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1681 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1682 /* If we do not have enough slots, grow the structure */
1683 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1684 /* need to grow file actions structure */
1685 if (_posix_spawn_file_actions_grow(psactsp
)) {
1691 * Allocate next available slot and fill it out
1693 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1695 psfileact
->psfaa_type
= PSFA_INHERIT
;
1696 psfileact
->psfaa_filedes
= filedes
;
1703 * posix_spawn_file_actions_addchdir_np
1705 * Description: Add a chdir action to the object referenced by 'file_actions'
1706 * that will cause the current working directory to attempt to be changed
1707 * to that referenced by 'path' in the spawned process.
1709 * Parameters: file_actions File action object to augment
1710 * path path of the desired working directory
1712 * Returns: 0 Success
1713 * ENOMEM Insufficient memory exists to add to
1714 * the spawn file actions object.
1715 * ENAMETOOLONG The supplied path exceeded PATH_MAX.
1717 * NOTIMP: Allowed failures (checking NOT required):
1718 * EINVAL The value specified by file_actions is invalid.
1721 posix_spawn_file_actions_addchdir_np(
1722 posix_spawn_file_actions_t
* __restrict file_actions
,
1723 const char * __restrict path
)
1725 _posix_spawn_file_actions_t
*psactsp
;
1726 _psfa_action_t
*psfileact
;
1728 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1732 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1734 /* If we do not have enough slots, grow the structure */
1735 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1736 /* need to grow file actions structure */
1737 if (_posix_spawn_file_actions_grow(psactsp
)) {
1743 * Allocate next available slot and fill it out
1745 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1747 psfileact
->psfaa_type
= PSFA_CHDIR
;
1748 if (strlcpy(psfileact
->psfaa_chdirargs
.psfac_path
, path
, PATH_MAX
) >= PATH_MAX
) {
1749 (*psactsp
)->psfa_act_count
--;
1750 return ENAMETOOLONG
;
1758 * posix_spawn_file_actions_fchdir_np
1760 * Description: Add a fchdir action to the object referenced by 'file_actions'
1761 * that will cause the current working directory to attempt to be changed
1762 * to that referenced by the descriptor 'filedes' in the spawned process.
1764 * Parameters: file_actions File action object to augment
1765 * filedes fd to chdir to
1767 * Returns: 0 Success
1768 * EBADF The value specified by either fildes is negative or
1769 * greater than or equal to {OPEN_MAX}.
1770 * ENOMEM Insufficient memory exists to add to
1771 * the spawn file actions object.
1773 * NOTIMP: Allowed failures (checking NOT required):
1774 * EINVAL The value specified by file_actions is invalid.
1777 posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t
*file_actions
,
1780 _posix_spawn_file_actions_t
*psactsp
;
1781 _psfa_action_t
*psfileact
;
1783 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1787 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1788 /* Range check; in spirit of POSIX */
1789 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1793 /* If we do not have enough slots, grow the structure */
1794 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1795 /* need to grow file actions structure */
1796 if (_posix_spawn_file_actions_grow(psactsp
)) {
1802 * Allocate next available slot and fill it out
1804 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1806 psfileact
->psfaa_type
= PSFA_FCHDIR
;
1807 psfileact
->psfaa_filedes
= filedes
;
1813 posix_spawnattr_setcpumonitor_default(posix_spawnattr_t
* __restrict attr
)
1815 return posix_spawnattr_setcpumonitor(attr
, PROC_POLICY_CPUMON_DEFAULTS
, 0);
1819 posix_spawnattr_setcpumonitor(posix_spawnattr_t
* __restrict attr
,
1820 uint64_t percent
, uint64_t interval
)
1822 _posix_spawnattr_t psattr
;
1824 if (attr
== NULL
|| *attr
== NULL
) {
1828 psattr
= *(_posix_spawnattr_t
*)attr
;
1830 psattr
->psa_cpumonitor_percent
= percent
;
1831 psattr
->psa_cpumonitor_interval
= interval
;
1837 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1838 uint64_t *percent
, uint64_t *interval
)
1840 _posix_spawnattr_t psattr
;
1842 if (attr
== NULL
|| *attr
== NULL
) {
1846 psattr
= *(_posix_spawnattr_t
*)attr
;
1848 *percent
= psattr
->psa_cpumonitor_percent
;
1849 *interval
= psattr
->psa_cpumonitor_interval
;
1854 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
1856 * posix_spawnattr_setjetsam
1858 * Description: Set jetsam attributes for the spawn attribute object
1859 * referred to by 'attr'.
1861 * Parameters: flags The flags value to set
1862 * priority Relative jetsam priority
1863 * memlimit Value in megabytes; a memory footprint
1864 * above this level may result in termination.
1865 * Implies both active and inactive limits.
1867 * Returns: 0 Success
1869 * Note: to be deprecated (not available on desktop)
1873 posix_spawnattr_setjetsam(posix_spawnattr_t
* __restrict attr
,
1874 short flags
, int priority
, int memlimit
)
1876 short flags_ext
= flags
;
1878 if (flags
& POSIX_SPAWN_JETSAM_MEMLIMIT_FATAL
) {
1879 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1880 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1882 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1883 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1886 return posix_spawnattr_setjetsam_ext(attr
, flags_ext
, priority
, memlimit
, memlimit
);
1888 #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
1891 * posix_spawnattr_setjetsam_ext
1893 * Description: Set jetsam attributes for the spawn attribute object
1894 * referred to by 'attr'.
1896 * Parameters: flags The flags value to set
1897 * priority Relative jetsam priority
1898 * memlimit_active Value in megabytes; memory footprint
1899 * above this level while process is
1900 * active may result in termination.
1901 * memlimit_inactive Value in megabytes; memory footprint
1902 * above this level while process is
1903 * inactive may result in termination.
1905 * Returns: 0 Success
1908 posix_spawnattr_setjetsam_ext(posix_spawnattr_t
* __restrict attr
,
1909 short flags
, int priority
, int memlimit_active
, int memlimit_inactive
)
1911 _posix_spawnattr_t psattr
;
1913 if (attr
== NULL
|| *attr
== NULL
) {
1917 psattr
= *(_posix_spawnattr_t
*)attr
;
1919 psattr
->psa_jetsam_flags
= flags
;
1920 psattr
->psa_jetsam_flags
|= POSIX_SPAWN_JETSAM_SET
;
1921 psattr
->psa_priority
= priority
;
1922 psattr
->psa_memlimit_active
= memlimit_active
;
1923 psattr
->psa_memlimit_inactive
= memlimit_inactive
;
1929 posix_spawnattr_set_threadlimit_ext(posix_spawnattr_t
* __restrict attr
,
1932 _posix_spawnattr_t psattr
;
1934 if (attr
== NULL
|| *attr
== NULL
) {
1938 psattr
= *(_posix_spawnattr_t
*)attr
;
1940 psattr
->psa_thread_limit
= thread_limit
;
1947 * posix_spawnattr_set_importancewatch_port_np
1949 * Description: Mark ports referred to by these rights
1950 * to boost the new task instead of their current task
1951 * for the spawn attribute object referred to by 'attr'.
1952 * Ports must be valid at posix_spawn time. They will NOT be
1953 * consumed by the kernel, so they must be deallocated after the spawn returns.
1954 * (If you are SETEXEC-ing, they are cleaned up by the exec operation).
1956 * The maximum number of watch ports allowed is defined by POSIX_SPAWN_IMPORTANCE_PORT_COUNT.
1958 * Parameters: count Number of ports in portarray
1959 * portarray Array of rights
1961 * Returns: 0 Success
1962 * EINVAL Bad port count
1963 * ENOMEM Insufficient memory exists to add to
1964 * the spawn port actions object.
1967 posix_spawnattr_set_importancewatch_port_np(posix_spawnattr_t
* __restrict attr
,
1968 int count
, mach_port_t portarray
[])
1972 if (count
< 0 || count
> POSIX_SPAWN_IMPORTANCE_PORT_COUNT
) {
1976 for (i
= 0; i
< count
; i
++) {
1977 _ps_port_action_t action
= {
1978 .port_type
= PSPA_IMP_WATCHPORTS
,
1979 .new_port
= portarray
[i
],
1981 err
= posix_spawn_appendportaction_np(attr
, &action
);
1990 posix_spawnattr_set_registered_ports_np(posix_spawnattr_t
* __restrict attr
,
1991 mach_port_t portarray
[], uint32_t count
)
1995 if (count
> TASK_PORT_REGISTER_MAX
) {
1999 for (uint32_t i
= 0; i
< count
; i
++) {
2000 _ps_port_action_t action
= {
2001 .port_type
= PSPA_REGISTERED_PORTS
,
2002 .new_port
= portarray
[i
],
2004 err
= posix_spawn_appendportaction_np(attr
, &action
);
2013 posix_spawnattr_set_ptrauth_task_port_np(posix_spawnattr_t
* __restrict attr
,
2018 _ps_port_action_t action
= {
2019 .port_type
= PSPA_PTRAUTH_TASK_PORT
,
2023 err
= posix_spawn_appendportaction_np(attr
, &action
);
2028 _ps_mac_policy_extension_t
*
2029 posix_spawnattr_macpolicyinfo_lookup(_posix_spawn_mac_policy_extensions_t psmx
, const char *policyname
)
2037 for (i
= 0; i
< psmx
->psmx_count
; i
++) {
2038 _ps_mac_policy_extension_t
*extension
= &psmx
->psmx_extensions
[i
];
2039 if (strcmp(extension
->policyname
, policyname
) == 0) {
2047 posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t
* __restrict attr
,
2048 const char *policyname
, void **datap
, size_t *datalenp
)
2050 _posix_spawnattr_t psattr
;
2051 _ps_mac_policy_extension_t
*extension
;
2053 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
|| datap
== NULL
) {
2057 psattr
= *(_posix_spawnattr_t
*)attr
;
2058 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
2059 if (extension
== NULL
) {
2062 *datap
= (void *)(uintptr_t)extension
->data
;
2063 if (datalenp
!= NULL
) {
2064 *datalenp
= (size_t)extension
->datalen
;
2070 posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t
* __restrict attr
,
2071 const char *policyname
, void *data
, size_t datalen
)
2073 _posix_spawnattr_t psattr
;
2074 _posix_spawn_mac_policy_extensions_t psmx
;
2075 _ps_mac_policy_extension_t
*extension
;
2077 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
) {
2081 psattr
= *(_posix_spawnattr_t
*)attr
;
2082 psmx
= psattr
->psa_mac_extensions
;
2083 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
2084 if (extension
!= NULL
) {
2085 extension
->data
= (uintptr_t)data
;
2086 extension
->datalen
= datalen
;
2088 } else if (psmx
== NULL
) {
2089 psmx
= psattr
->psa_mac_extensions
= malloc(PS_MAC_EXTENSIONS_SIZE(PS_MAC_EXTENSIONS_INIT_COUNT
));
2093 psmx
->psmx_alloc
= PS_MAC_EXTENSIONS_INIT_COUNT
;
2094 psmx
->psmx_count
= 0;
2095 } else if (psmx
->psmx_count
== psmx
->psmx_alloc
) {
2097 if (os_mul_overflow(psmx
->psmx_alloc
, 2, &newnum
)) {
2100 size_t extsize
= PS_MAC_EXTENSIONS_SIZE(newnum
);
2104 psmx
= psattr
->psa_mac_extensions
= reallocf(psmx
, extsize
);
2108 psmx
->psmx_alloc
= newnum
;
2110 extension
= &psmx
->psmx_extensions
[psmx
->psmx_count
];
2111 strlcpy(extension
->policyname
, policyname
, sizeof(extension
->policyname
));
2112 extension
->data
= (uintptr_t)data
;
2113 extension
->datalen
= datalen
;
2114 psmx
->psmx_count
+= 1;
2119 * posix_spawn_destroymacpolicy_info_np
2120 * Description: cleanup the macpolicy struct in posix_spawnattr_t attr
2123 posix_spawn_destroymacpolicy_info_np(posix_spawnattr_t
*attr
)
2125 _posix_spawnattr_t psattr
;
2126 _posix_spawn_mac_policy_extensions_t psmx
;
2128 if (attr
== NULL
|| *attr
== NULL
) {
2132 psattr
= *(_posix_spawnattr_t
*)attr
;
2133 psmx
= psattr
->psa_mac_extensions
;
2138 psattr
->psa_mac_extensions
= NULL
;
2144 posix_spawnattr_setcoalition_np(const posix_spawnattr_t
* __restrict attr
,
2145 uint64_t coalitionid
, int type
, int role
)
2147 _posix_spawnattr_t psattr
;
2148 struct _posix_spawn_coalition_info
*coal_info
;
2150 if (attr
== NULL
|| *attr
== NULL
) {
2153 if (type
< 0 || type
> COALITION_TYPE_MAX
) {
2157 psattr
= *(_posix_spawnattr_t
*)attr
;
2159 coal_info
= psattr
->psa_coalition_info
;
2161 coal_info
= (struct _posix_spawn_coalition_info
*)malloc(sizeof(*coal_info
));
2165 memset(coal_info
, 0, sizeof(*coal_info
));
2166 psattr
->psa_coalition_info
= coal_info
;
2169 coal_info
->psci_info
[type
].psci_id
= coalitionid
;
2170 coal_info
->psci_info
[type
].psci_role
= role
;
2177 posix_spawnattr_set_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t qos_clamp
)
2179 _posix_spawnattr_t psattr
;
2181 if (attr
== NULL
|| *attr
== NULL
) {
2185 if (qos_clamp
>= POSIX_SPAWN_PROC_CLAMP_LAST
) {
2189 psattr
= *(_posix_spawnattr_t
*)attr
;
2190 psattr
->psa_qos_clamp
= qos_clamp
;
2196 posix_spawnattr_get_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict qos_clampp
)
2198 _posix_spawnattr_t psattr
;
2200 if (attr
== NULL
|| *attr
== NULL
) {
2204 psattr
= *(_posix_spawnattr_t
*)attr
;
2205 *qos_clampp
= psattr
->psa_qos_clamp
;
2211 posix_spawnattr_set_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t darwin_role
)
2213 _posix_spawnattr_t psattr
;
2215 if (attr
== NULL
|| *attr
== NULL
) {
2219 psattr
= *(_posix_spawnattr_t
*)attr
;
2220 psattr
->psa_darwin_role
= darwin_role
;
2226 posix_spawnattr_get_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict darwin_rolep
)
2228 _posix_spawnattr_t psattr
;
2230 if (attr
== NULL
|| *attr
== NULL
) {
2234 psattr
= *(_posix_spawnattr_t
*)attr
;
2235 *darwin_rolep
= psattr
->psa_darwin_role
;
2242 posix_spawnattr_set_persona_np(const posix_spawnattr_t
* __restrict attr
, uid_t persona_id
, uint32_t flags
)
2244 _posix_spawnattr_t psattr
;
2245 struct _posix_spawn_persona_info
*persona
;
2247 if (attr
== NULL
|| *attr
== NULL
) {
2251 if (flags
& ~POSIX_SPAWN_PERSONA_ALL_FLAGS
) {
2255 psattr
= *(_posix_spawnattr_t
*)attr
;
2257 persona
= psattr
->psa_persona_info
;
2259 persona
= (struct _posix_spawn_persona_info
*)malloc(sizeof(*persona
));
2263 persona
->pspi_uid
= 0;
2264 persona
->pspi_gid
= 0;
2265 persona
->pspi_ngroups
= 0;
2266 persona
->pspi_groups
[0] = 0;
2267 persona
->pspi_gmuid
= 0;
2269 psattr
->psa_persona_info
= persona
;
2272 persona
->pspi_id
= persona_id
;
2273 persona
->pspi_flags
= flags
;
2279 posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t
* __restrict attr
, uid_t uid
)
2281 _posix_spawnattr_t psattr
;
2282 struct _posix_spawn_persona_info
*persona
;
2284 if (attr
== NULL
|| *attr
== NULL
) {
2288 psattr
= *(_posix_spawnattr_t
*)attr
;
2289 persona
= psattr
->psa_persona_info
;
2294 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
2298 persona
->pspi_uid
= uid
;
2300 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_UID
;
2306 posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t
* __restrict attr
, gid_t gid
)
2308 _posix_spawnattr_t psattr
;
2309 struct _posix_spawn_persona_info
*persona
;
2311 if (attr
== NULL
|| *attr
== NULL
) {
2315 psattr
= *(_posix_spawnattr_t
*)attr
;
2316 persona
= psattr
->psa_persona_info
;
2321 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
2325 persona
->pspi_gid
= gid
;
2327 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GID
;
2333 posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t
* __restrict attr
, int ngroups
, gid_t
*gidarray
, uid_t gmuid
)
2335 _posix_spawnattr_t psattr
;
2336 struct _posix_spawn_persona_info
*persona
;
2338 if (attr
== NULL
|| *attr
== NULL
) {
2342 if (gidarray
== NULL
) {
2346 if (ngroups
> NGROUPS
|| ngroups
< 0) {
2350 psattr
= *(_posix_spawnattr_t
*)attr
;
2351 persona
= psattr
->psa_persona_info
;
2356 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
2360 persona
->pspi_ngroups
= ngroups
;
2361 for (int i
= 0; i
< ngroups
; i
++) {
2362 persona
->pspi_groups
[i
] = gidarray
[i
];
2365 persona
->pspi_gmuid
= gmuid
;
2367 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GROUPS
;
2373 posix_spawnattr_set_max_addr_np(const posix_spawnattr_t
* __restrict attr
, uint64_t max_addr
)
2375 _posix_spawnattr_t psattr
;
2377 if (attr
== NULL
|| *attr
== NULL
) {
2381 psattr
= *(_posix_spawnattr_t
*)attr
;
2382 psattr
->psa_max_addr
= max_addr
;
2388 posix_spawnattr_setnosmt_np(const posix_spawnattr_t
* __restrict attr
)
2390 _posix_spawnattr_t psattr
;
2392 if (attr
== NULL
|| *attr
== NULL
) {
2396 psattr
= *(_posix_spawnattr_t
*)attr
;
2397 psattr
->psa_no_smt
= true;
2403 posix_spawnattr_set_csm_np(const posix_spawnattr_t
* __restrict attr
, uint32_t flags
)
2405 _posix_spawnattr_t psattr
;
2407 if (attr
== NULL
|| *attr
== NULL
) {
2411 const uint32_t mask
= POSIX_SPAWN_NP_CSM_ALL
| POSIX_SPAWN_NP_CSM_TECS
| POSIX_SPAWN_NP_CSM_NOSMT
;
2412 if ((flags
& ~mask
) != 0) {
2416 psattr
= *(_posix_spawnattr_t
*)attr
;
2418 if (flags
& (POSIX_SPAWN_NP_CSM_TECS
| POSIX_SPAWN_NP_CSM_ALL
)) {
2419 psattr
->psa_tecs
= true;
2421 if (flags
& (POSIX_SPAWN_NP_CSM_NOSMT
| POSIX_SPAWN_NP_CSM_ALL
)) {
2422 psattr
->psa_no_smt
= true;
2428 static struct _posix_spawn_posix_cred_info
*
2429 _posix_spawnattr_get_posix_creds_info(_posix_spawnattr_t psattr
)
2431 struct _posix_spawn_posix_cred_info
*pspci
= psattr
->psa_posix_cred_info
;
2433 if (pspci
== NULL
) {
2434 pspci
= malloc(sizeof(struct _posix_spawn_posix_cred_info
));
2435 if (pspci
!= NULL
) {
2436 pspci
->pspci_flags
= 0;
2437 pspci
->pspci_uid
= 0;
2438 pspci
->pspci_gid
= 0;
2439 pspci
->pspci_ngroups
= 0;
2440 pspci
->pspci_groups
[0] = 0;
2441 pspci
->pspci_gmuid
= 0;
2442 pspci
->pspci_login
[0] = '\0';
2443 psattr
->psa_posix_cred_info
= pspci
;
2450 posix_spawnattr_set_uid_np(const posix_spawnattr_t
*attr
, uid_t uid
)
2452 struct _posix_spawn_posix_cred_info
*pspci
;
2454 if (attr
== NULL
|| *attr
== NULL
) {
2458 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2459 if (pspci
== NULL
) {
2463 pspci
->pspci_uid
= uid
;
2465 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_UID
;
2471 posix_spawnattr_set_gid_np(const posix_spawnattr_t
*attr
, gid_t gid
)
2473 struct _posix_spawn_posix_cred_info
*pspci
;
2475 if (attr
== NULL
|| *attr
== NULL
) {
2479 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2480 if (pspci
== NULL
) {
2484 pspci
->pspci_gid
= gid
;
2486 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_GID
;
2492 posix_spawnattr_set_groups_np(const posix_spawnattr_t
*attr
,
2493 int ngroups
, gid_t
*gidarray
, uid_t gmuid
)
2495 struct _posix_spawn_posix_cred_info
*pspci
;
2497 if (attr
== NULL
|| *attr
== NULL
) {
2501 if (gidarray
== NULL
) {
2505 if (ngroups
> NGROUPS
|| ngroups
< 0) {
2509 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2510 if (pspci
== NULL
) {
2514 pspci
->pspci_ngroups
= ngroups
;
2515 for (int i
= 0; i
< ngroups
; i
++) {
2516 pspci
->pspci_groups
[i
] = gidarray
[i
];
2519 pspci
->pspci_gmuid
= gmuid
;
2521 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_GROUPS
;
2527 posix_spawnattr_set_login_np(const posix_spawnattr_t
*attr
, const char *login
)
2529 struct _posix_spawn_posix_cred_info
*pspci
;
2531 if (attr
== NULL
|| *attr
== NULL
) {
2535 if (strlen(login
) > MAXLOGNAME
) {
2539 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2540 if (pspci
== NULL
) {
2544 strlcpy(pspci
->pspci_login
, login
, sizeof(pspci
->pspci_login
));
2546 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_LOGIN
;
2552 * posix_spawnattr_set_jetsam_ttr_np
2554 * Description: Pass data regarding recent relaunch behavior when jetsammed for the process.
2555 * The recent history is effectively converted into a histogram and the highest
2556 * frequency bucket defines the "type" of the process. The type is passed along
2557 * to the jetsam code as part of psa_jetsam_flags.
2559 * Parameters: count Number of entries in the ttrs_millis array
2560 * ttrs_millis Array of raw data for relaunch behavior
2562 * Returns: 0 Success
2563 * EINVAL Bad attr pointer or empty data array
2566 posix_spawnattr_set_jetsam_ttr_np(const posix_spawnattr_t
* __restrict attr
, uint32_t count
, uint32_t *ttrs_millis
)
2568 _posix_spawnattr_t psattr
;
2571 * Define the bucketizing policy which would be used to generate the histogram. These
2572 * values are based on looking at data from various Avg. Joanna runs.
2574 static const uint32_t relaunch_buckets_msecs
[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
] = {
2579 static const uint32_t relaunch_jetsam_flags
[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
] = {
2580 POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_HIGH
,
2581 POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_MED
,
2582 POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_LOW
2585 /* Make sure the attr pointer is valid */
2586 if (attr
== NULL
|| *attr
== NULL
) {
2590 /* Make sure the count of entries is non-zero */
2595 psattr
= *(_posix_spawnattr_t
*)attr
;
2597 /* Generate a histogram based on the relaunch data while maintaining highest frequency bucket info */
2598 int relaunch_histogram
[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
] = {0};
2599 int max_frequency
= -1;
2600 int highest_frequency_bucket
= -1;
2602 for (uint32_t i
= 0; i
< count
; i
++) {
2603 /* For each data point passed in via launchd, find the bucket it lands in */
2604 for (uint32_t bucket
= 0; bucket
< POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
; bucket
++) {
2605 if (ttrs_millis
[i
] <= relaunch_buckets_msecs
[bucket
]) {
2606 relaunch_histogram
[bucket
]++;
2608 /* Check if the bucket is the highest frequency bucket now */
2609 if (relaunch_histogram
[bucket
] > max_frequency
) {
2610 max_frequency
= relaunch_histogram
[bucket
];
2611 highest_frequency_bucket
= bucket
;
2617 psattr
->psa_jetsam_flags
|= relaunch_jetsam_flags
[highest_frequency_bucket
];
2624 * Description: Create a new process from the process image corresponding to
2625 * the supplied 'path' argument.
2627 * Parameters: pid Pointer to pid_t to receive the
2628 * PID of the spawned process, if
2629 * successful and 'pid' != NULL
2630 * path Path of image file to spawn
2631 * file_actions spawn file actions object which
2632 * describes file actions to be
2633 * performed during the spawn
2634 * attrp spawn attributes object which
2635 * describes attributes to be
2636 * applied during the spawn
2637 * argv argument vector array; NULL
2639 * envp environment vector array; NULL
2642 * Returns: 0 Success
2643 * !0 An errno value indicating the
2644 * cause of the failure to spawn
2646 * Notes: Unlike other system calls, the return value of this system
2647 * call is expected to either be a 0 or an errno, rather than a
2648 * 0 or a -1, with the 'errno' variable being set.
2650 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
2651 struct _posix_spawn_args_desc
*,
2652 char *const argv
[__restrict
], char *const envp
[__restrict
]);
2655 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
2656 const posix_spawn_file_actions_t
*file_actions
,
2657 const posix_spawnattr_t
* __restrict attrp
,
2658 char *const argv
[__restrict
], char *const envp
[__restrict
])
2660 int saveerrno
= errno
;
2663 * Only do extra work if we have file actions or attributes to push
2664 * down. We use a descriptor to push this information down, since we
2665 * want to have size information, which will let us (1) preallocate a
2666 * single chunk of memory for the copyin(), and (2) allow us to do a
2667 * single copyin() per attributes or file actions as a monlithic block.
2669 * Note: A future implementation may attempt to do the same
2670 * thing for the argv/envp data, which could potentially
2671 * result in a performance improvement due to increased
2672 * kernel efficiency, even though it would mean copying
2673 * the data in user space.
2675 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
2676 struct _posix_spawn_args_desc ad
;
2678 memset(&ad
, 0, sizeof(ad
));
2679 if (attrp
!= NULL
&& *attrp
!= NULL
) {
2680 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
2681 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
2684 if (psattr
->psa_ports
!= NULL
) {
2685 size_t psact_size
= PS_PORT_ACTIONS_SIZE(psattr
->psa_ports
->pspa_count
);
2686 if (psact_size
== 0 && psattr
->psa_ports
->pspa_count
!= 0) {
2691 ad
.port_actions
= psattr
->psa_ports
;
2692 ad
.port_actions_size
= psact_size
;
2694 if (psattr
->psa_mac_extensions
!= NULL
) {
2695 size_t macext_size
= PS_MAC_EXTENSIONS_SIZE(psattr
->psa_mac_extensions
->psmx_count
);
2696 if (macext_size
== 0 && psattr
->psa_mac_extensions
->psmx_count
!= 0) {
2701 ad
.mac_extensions
= psattr
->psa_mac_extensions
;
2702 ad
.mac_extensions_size
= macext_size
;
2704 if (psattr
->psa_coalition_info
!= NULL
) {
2705 ad
.coal_info_size
= sizeof(struct _posix_spawn_coalition_info
);
2706 ad
.coal_info
= psattr
->psa_coalition_info
;
2708 if (psattr
->psa_persona_info
!= NULL
) {
2709 ad
.persona_info_size
= sizeof(struct _posix_spawn_persona_info
);
2710 ad
.persona_info
= psattr
->psa_persona_info
;
2712 if (psattr
->psa_posix_cred_info
!= NULL
) {
2713 ad
.posix_cred_info_size
= sizeof(struct _posix_spawn_posix_cred_info
);
2714 ad
.posix_cred_info
= psattr
->psa_posix_cred_info
;
2716 if (psattr
->psa_subsystem_root_path
!= NULL
) {
2717 ad
.subsystem_root_path_size
= MAXPATHLEN
;
2718 ad
.subsystem_root_path
= psattr
->psa_subsystem_root_path
;
2721 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
2722 _posix_spawn_file_actions_t psactsp
=
2723 *(_posix_spawn_file_actions_t
*)file_actions
;
2725 if (psactsp
->psfa_act_count
> 0) {
2726 size_t fa_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
2727 if (fa_size
== 0 && psactsp
->psfa_act_count
!= 0) {
2732 ad
.file_actions_size
= fa_size
;
2733 ad
.file_actions
= psactsp
;
2737 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
2739 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);