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/exception_types.h>
41 #include <mach/coalition.h> /* for COALITION_TYPE_MAX */
42 #include <sys/kern_memorystatus.h>
45 * posix_spawnattr_init
47 * Description: Initialize a spawn attributes object attr with default values
49 * Parameters: attr The spawn attributes object to be
53 * ENOMEM Insufficient memory exists to
54 * initialize the spawn attributes object.
56 * Note: As an implementation detail, the externally visibily type
57 * posix_spawnattr_t is defined to be a void *, and initialization
58 * involves allocation of a memory object. Subsequent changes to
59 * the spawn attributes may result in reallocation under the
62 * Reinitialization of an already initialized spawn attributes
63 * object will result in memory being leaked. Because spawn
64 * attributes are not required to be used in conjunction with a
65 * static initializer, there is no way to distinguish a spawn
66 * attribute with stack garbage from one that's been initialized.
67 * This is arguably an API design error.
70 posix_spawnattr_init(posix_spawnattr_t
*attr
)
72 _posix_spawnattr_t
*psattrp
= (_posix_spawnattr_t
*)attr
;
75 if ((*psattrp
= (_posix_spawnattr_t
)malloc(sizeof(struct _posix_spawnattr
))) == NULL
) {
79 * The default value of this attribute shall be as if no
82 (*psattrp
)->psa_flags
= 0;
85 * The default value of this attribute shall be an empty
88 (*psattrp
)->psa_sigdefault
= 0;
90 /* The default value of this attribute is unspecified */
91 (*psattrp
)->psa_sigmask
= 0;
93 /* The default value of this attribute shall be zero */
94 (*psattrp
)->psa_pgroup
= 0; /* doesn't matter */
96 /* Default is no binary preferences, i.e. use normal grading */
97 memset((*psattrp
)->psa_binprefs
, 0,
98 sizeof((*psattrp
)->psa_binprefs
));
100 /* Default is no port actions to take */
101 (*psattrp
)->psa_ports
= NULL
;
104 * The default value of this attribute shall be an no
105 * process control on resource starvation
107 (*psattrp
)->psa_pcontrol
= 0;
110 * Initializing the alignment paddings.
113 (*psattrp
)->short_padding
= 0;
114 (*psattrp
)->flags_padding
= 0;
116 /* Default is no new apptype requested */
117 (*psattrp
)->psa_apptype
= POSIX_SPAWN_PROCESS_TYPE_DEFAULT
;
120 (*psattrp
)->psa_jetsam_flags
= 0;
121 (*psattrp
)->psa_priority
= -1;
122 (*psattrp
)->psa_memlimit_active
= -1;
123 (*psattrp
)->psa_memlimit_inactive
= -1;
125 /* Default is no thread limit */
126 (*psattrp
)->psa_thread_limit
= 0;
128 /* Default is no CPU usage monitor active. */
129 (*psattrp
)->psa_cpumonitor_percent
= 0;
130 (*psattrp
)->psa_cpumonitor_interval
= 0;
132 /* Default is no MAC policy extensions. */
133 (*psattrp
)->psa_mac_extensions
= NULL
;
135 /* Default is to inherit parent's coalition(s) */
136 (*psattrp
)->psa_coalition_info
= NULL
;
138 (*psattrp
)->psa_persona_info
= NULL
;
141 * old coalition field
142 * For backwards compatibility reasons, we set this to 1
143 * which is the first valid coalition id. This will allow
144 * newer user space code to properly spawn processes on
146 * (they will just all end up in the same coalition).
148 (*psattrp
)->psa_reserved
= 1;
150 /* Default is no new clamp */
151 (*psattrp
)->psa_qos_clamp
= POSIX_SPAWN_PROC_CLAMP_NONE
;
153 /* Default is no change to role */
154 (*psattrp
)->psa_darwin_role
= POSIX_SPAWN_DARWIN_ROLE_NONE
;
156 (*psattrp
)->psa_max_addr
= 0;
164 * posix_spawnattr_destroy
166 * Description: Destroy a spawn attributes object that was previously
167 * initialized via posix_spawnattr_init() by freeing any
168 * memory associated with it and setting it to an invalid value.
170 * Parameters: attr The spawn attributes object to be
175 * Notes: The destroyed spawn attribute results in the void * pointer
176 * being set to NULL; subsequent use without reinitialization
177 * will result in explicit program failure (rather than merely
178 * "undefined behaviour").
180 * NOTIMP: Allowed failures (checking NOT required):
181 * EINVAL The value specified by attr is invalid.
183 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
184 static int posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*);
185 static int posix_spawn_destroypersona_info_np(posix_spawnattr_t
*);
188 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
190 _posix_spawnattr_t psattr
;
192 if (attr
== NULL
|| *attr
== NULL
) {
196 psattr
= *(_posix_spawnattr_t
*)attr
;
197 posix_spawn_destroyportactions_np(attr
);
198 posix_spawn_destroycoalition_info_np(attr
);
199 posix_spawn_destroypersona_info_np(attr
);
209 * posix_spawnattr_setflags
211 * Description: Set the spawn flags attribute for the spawn attribute object
212 * referred to by 'attr'.
214 * Parameters: attr The spawn attributes object whose flags
216 * flags The flags value to set
220 * NOTIMP: Allowed failures (checking NOT required):
221 * EINVAL The value specified by attr is invalid.
222 * EINVAL The value of the attribute being set is not valid.
225 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
227 _posix_spawnattr_t psattr
;
229 if (attr
== NULL
|| *attr
== NULL
) {
233 psattr
= *(_posix_spawnattr_t
*)attr
;
234 psattr
->psa_flags
= flags
;
241 * posix_spawnattr_getflags
243 * Description: Retrieve the spawn attributes flag for the spawn attributes
244 * object referenced by 'attr' and place them in the memory
245 * location referenced by 'flagsp'
247 * Parameters: attr The spawn attributes object whose flags
248 * are to be retrieved
249 * flagsp A pointer to a short value to receive
255 * *flagps (modified) The flags value from the spawn
258 * NOTIMP: Allowed failures (checking NOT required):
259 * EINVAL The value specified by attr is invalid.
260 * EINVAL The value of the attribute being set is not valid.
263 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
264 short * __restrict flagsp
)
266 _posix_spawnattr_t psattr
;
268 if (attr
== NULL
|| *attr
== NULL
) {
272 psattr
= *(_posix_spawnattr_t
*)attr
;
273 *flagsp
= psattr
->psa_flags
;
280 * posix_spawnattr_getsigdefault
282 * Description: Retrieve the set of signals to be set to default according to
283 * the spawn attribute value referenced by 'attr' and place the
284 * result into the memory containing the sigset_t referenced by
287 * Parameters: attr The spawn attributes object whose
288 * signal set for default signals is to
290 * sigdefault A pointer to the sigset_t to receive
296 * *sigdefault (modified) The signal set of signals to default
297 * from the spawn attributes object
300 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
301 sigset_t
* __restrict sigdefault
)
303 _posix_spawnattr_t psattr
;
305 if (attr
== NULL
|| *attr
== NULL
) {
309 psattr
= *(_posix_spawnattr_t
*)attr
;
310 *sigdefault
= psattr
->psa_sigdefault
;
317 * posix_spawnattr_getpgroup
319 * Description: Obtain the value of the spawn process group attribute from the
320 * spawn attributes object referenced by 'attr' and place the
321 * results in the memory location referenced by 'pgroup'
323 * Parameters: attr The spawn attributes object whose
324 * process group information is to be
326 * pgroup A pointer to the pid_t to receive the
332 * *pgroup (modified) The process group information from the
333 * spawn attributes object
336 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
337 pid_t
* __restrict pgroup
)
339 _posix_spawnattr_t psattr
;
341 if (attr
== NULL
|| *attr
== NULL
) {
345 psattr
= *(_posix_spawnattr_t
*)attr
;
346 *pgroup
= psattr
->psa_pgroup
;
353 * posix_spawnattr_getsigmask
355 * Description: Obtain the value of the spawn signal mask attribute from the
356 * spawn attributes object referenced by 'attr' and place the
357 * result into the memory containing the sigset_t referenced by
360 * Parameters: attr The spawn attributes object whose
361 * signal set for masked signals is to
363 * sigmask A pointer to the sigset_t to receive
369 * *sigmask (modified) The signal set of signals to mask
370 * from the spawn attributes object
373 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
374 sigset_t
* __restrict sigmask
)
376 _posix_spawnattr_t psattr
;
378 if (attr
== NULL
|| *attr
== NULL
) {
382 psattr
= *(_posix_spawnattr_t
*)attr
;
383 *sigmask
= psattr
->psa_sigmask
;
389 * posix_spawnattr_getbinpref_np
391 * Description: Obtain the value of the spawn binary preferences attribute from
392 * the spawn attributes object referenced by 'attr' and place the
393 * result into the memory referenced by 'pref'.
395 * Parameters: attr The spawn attributes object whose
396 * binary preferences are to be retrieved
397 * count The size of the cpu_type_t array
398 * pref An array of cpu types
399 * ocount The actual number copied
401 * Returns: 0 No binary preferences found
402 * > 0 The number of cpu types (less than
403 * count) copied over from 'attr'.
406 * *pref (modified) The binary preferences array
407 * from the spawn attributes object
410 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
411 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
413 _posix_spawnattr_t psattr
;
416 if (attr
== NULL
|| *attr
== NULL
) {
420 psattr
= *(_posix_spawnattr_t
*)attr
;
421 for (i
= 0; i
< count
&& i
< 4; i
++) {
422 pref
[i
] = psattr
->psa_binprefs
[i
];
433 * posix_spawnattr_getpcontrol_np
435 * Description: Retrieve the process control property set default according to
436 * the spawn attribute value referenced by 'attr' and place the
437 * result into the memory containing the control referenced by
440 * Parameters: attr The spawn attributes object whose
441 * signal set for default signals is to
443 * pcontrol A pointer to an int to receive
444 * the process control info
449 * *pcontrol (modified) The signal set of signals to default
450 * from the spawn attributes object
453 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
454 int * __restrict pcontrol
)
456 _posix_spawnattr_t psattr
;
458 if (attr
== NULL
|| *attr
== NULL
) {
462 psattr
= *(_posix_spawnattr_t
*)attr
;
463 *pcontrol
= psattr
->psa_pcontrol
;
469 * posix_spawnattr_getprocesstype_np
471 * Description: Retrieve the process specific behaviors and app launch types
472 * spawn attribute value referenced by 'attr' and place the
473 * result into the memory containing the control referenced by
476 * Parameters: attr The spawn attributes object whose
477 * signal set for default signals is to
479 * proctype A pointer to an int to receive
480 * the process type info
485 * *proctype (modified) The process type set to value
486 * from the spawn attributes object
489 posix_spawnattr_getprocesstype_np(const posix_spawnattr_t
* __restrict attr
,
490 int * __restrict proctype
)
492 _posix_spawnattr_t psattr
;
494 if (attr
== NULL
|| *attr
== NULL
) {
498 psattr
= *(_posix_spawnattr_t
*)attr
;
499 *proctype
= psattr
->psa_apptype
;
504 * posix_spawnattr_setsigdefault
506 * Description: Set the set of signals to be set to default for the spawn
507 * attribute value referenced by 'attr' from the memory
508 * containing the sigset_t referenced by 'sigdefault'
510 * Parameters: attr The spawn attributes object whose
511 * signal set for default signals is to
513 * sigdefault A pointer to the sigset_t from which to
514 * obtain the signal set
519 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
520 const sigset_t
* __restrict sigdefault
)
522 _posix_spawnattr_t psattr
;
524 if (attr
== NULL
|| *attr
== NULL
) {
528 psattr
= *(_posix_spawnattr_t
*)attr
;
529 psattr
->psa_sigdefault
= *sigdefault
;
536 * posix_spawnattr_setpgroup
538 * Description: Set the value of the spawn process group attribute for the
539 * spawn attributes object referenced by 'attr' from the value
542 * Parameters: attr The spawn attributes object for which
543 * the process group information is to be
545 * pgroup The process group to set
550 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
552 _posix_spawnattr_t psattr
;
554 if (attr
== NULL
|| *attr
== NULL
) {
558 psattr
= *(_posix_spawnattr_t
*)attr
;
559 psattr
->psa_pgroup
= pgroup
;
566 * posix_spawnattr_setsigmask
568 * Description: Set the set of signals to be masked for the spawn attribute
569 * value referenced by 'attr' from the memory containing the
570 * sigset_t referenced by 'sigmask'
572 * Parameters: attr The spawn attributes object whose
573 * signal set for masked signals is to
575 * sigmask A pointer to the sigset_t from which to
576 * obtain the signal set
581 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
582 const sigset_t
* __restrict sigmask
)
584 _posix_spawnattr_t psattr
;
586 if (attr
== NULL
|| *attr
== NULL
) {
590 psattr
= *(_posix_spawnattr_t
*)attr
;
591 psattr
->psa_sigmask
= *sigmask
;
598 * posix_spawnattr_setbinpref_np
600 * Description: Set the universal binary preferences for the spawn attribute
601 * value referenced by 'attr' from the memory containing the
602 * cpu_type_t array referenced by 'pref', size of 'count'
604 * Parameters: attr The spawn attributes object whose
605 * binary preferences are to be set
606 * count Size of the array pointed to by 'pref'
607 * pref cpu_type_t array of binary preferences
608 * ocount The actual number copied
610 * Returns: 0 No preferences copied
611 * > 0 Number of preferences copied
613 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
614 * If the caller provides more preferences than this limit, they
615 * will be ignored, as reflected in the return value.
618 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
619 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
621 _posix_spawnattr_t psattr
;
624 if (attr
== NULL
|| *attr
== NULL
) {
628 psattr
= *(_posix_spawnattr_t
*)attr
;
629 for (i
= 0; i
< count
&& i
< 4; i
++) {
630 psattr
->psa_binprefs
[i
] = pref
[i
];
633 /* return number of binprefs copied over */
642 * posix_spawnattr_setpcontrol_np
644 * Description: Set the process control property according to
645 * attribute value referenced by 'attr' from the memory
646 * containing the int value 'pcontrol'
648 * Parameters: attr The spawn attributes object whose
649 * signal set for default signals is to
651 * pcontrol An int value of the process control info
656 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
659 _posix_spawnattr_t psattr
;
661 if (attr
== NULL
|| *attr
== NULL
) {
665 psattr
= *(_posix_spawnattr_t
*)attr
;
666 psattr
->psa_pcontrol
= pcontrol
;
673 * posix_spawnattr_setprocesstype_np
675 * Description: Set the process specific behaviors and app launch type
676 * attribute value referenced by 'attr' from the memory
677 * containing the int value 'proctype'
679 * Parameters: attr The spawn attributes object whose
680 * signal set for default signals is to
682 * proctype An int value of the process type info
687 posix_spawnattr_setprocesstype_np(posix_spawnattr_t
* __restrict attr
,
690 _posix_spawnattr_t psattr
;
692 if (attr
== NULL
|| *attr
== NULL
) {
696 psattr
= *(_posix_spawnattr_t
*)attr
;
697 psattr
->psa_apptype
= proctype
;
703 * posix_spawn_createportactions_np
704 * Description: create a new posix_spawn_port_actions struct and link
705 * it into the posix_spawnattr.
708 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
710 _posix_spawnattr_t psattr
;
711 _posix_spawn_port_actions_t acts
;
713 if (attr
== NULL
|| *attr
== NULL
) {
717 psattr
= *(_posix_spawnattr_t
*)attr
;
718 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
723 acts
->pspa_alloc
= 2;
724 acts
->pspa_count
= 0;
726 psattr
->psa_ports
= acts
;
731 * posix_spawn_growportactions_np
732 * Description: Enlarge the size of portactions if necessary
735 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
737 _posix_spawnattr_t psattr
;
738 _posix_spawn_port_actions_t acts
;
740 if (attr
== NULL
|| *attr
== NULL
) {
744 psattr
= *(_posix_spawnattr_t
*)attr
;
745 acts
= psattr
->psa_ports
;
750 /* Double number of port actions allocated for */
752 if (os_mul_overflow(acts
->pspa_alloc
, 2, &newnum
)) {
755 size_t newsize
= PS_PORT_ACTIONS_SIZE(newnum
);
760 acts
= realloc(acts
, newsize
);
765 acts
->pspa_alloc
= newnum
;
766 psattr
->psa_ports
= acts
;
771 * posix_spawn_destroyportactions_np
772 * Description: clean up portactions struct in posix_spawnattr_t attr
775 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
777 _posix_spawnattr_t psattr
;
778 _posix_spawn_port_actions_t acts
;
780 if (attr
== NULL
|| *attr
== NULL
) {
784 psattr
= *(_posix_spawnattr_t
*)attr
;
785 acts
= psattr
->psa_ports
;
795 * posix_spawn_destroycoalition_info_np
796 * Description: clean up coalition_info struct in posix_spawnattr_t attr
799 posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*attr
)
801 _posix_spawnattr_t psattr
;
802 struct _posix_spawn_coalition_info
*coal_info
;
804 if (attr
== NULL
|| *attr
== NULL
) {
808 psattr
= *(_posix_spawnattr_t
*)attr
;
809 coal_info
= psattr
->psa_coalition_info
;
810 if (coal_info
== NULL
) {
814 psattr
->psa_coalition_info
= NULL
;
820 * posix_spawn_destroypersona_info_np
821 * Description: clean up persona_info struct in posix_spawnattr_t attr
824 posix_spawn_destroypersona_info_np(posix_spawnattr_t
*attr
)
826 _posix_spawnattr_t psattr
;
827 struct _posix_spawn_persona_info
*persona
;
829 if (attr
== NULL
|| *attr
== NULL
) {
833 psattr
= *(_posix_spawnattr_t
*)attr
;
834 persona
= psattr
->psa_persona_info
;
835 if (persona
== NULL
) {
839 psattr
->psa_persona_info
= NULL
;
845 * posix_spawn_appendportaction_np
846 * Description: append a port action, grow the array if necessary
849 posix_spawn_appendportaction_np(posix_spawnattr_t
*attr
, _ps_port_action_t
*act
)
851 _posix_spawnattr_t psattr
;
852 _posix_spawn_port_actions_t acts
;
854 if (attr
== NULL
|| *attr
== NULL
|| act
== NULL
) {
858 psattr
= *(_posix_spawnattr_t
*)attr
;
859 acts
= psattr
->psa_ports
;
861 // Have any port actions been created yet?
863 int err
= posix_spawn_createportactions_np(attr
);
867 acts
= psattr
->psa_ports
;
870 // Is there enough room?
871 if (acts
->pspa_alloc
== acts
->pspa_count
) {
872 int err
= posix_spawn_growportactions_np(attr
);
876 acts
= psattr
->psa_ports
;
879 // Add this action to next spot in array
880 acts
->pspa_actions
[acts
->pspa_count
] = *act
;
887 * posix_spawnattr_setspecialport_np
889 * Description: Set a new value for a mach special port in the spawned task.
891 * Parameters: attr The spawn attributes object for the
893 * new_port The new value for the special port
894 * which The particular port to be set
895 * (see task_set_special_port for details)
898 * ENOMEM Couldn't allocate memory
901 posix_spawnattr_setspecialport_np(
902 posix_spawnattr_t
*attr
,
903 mach_port_t new_port
,
906 _ps_port_action_t action
= {
907 .port_type
= PSPA_SPECIAL
,
908 .new_port
= new_port
,
911 return posix_spawn_appendportaction_np(attr
, &action
);
915 * posix_spawnattr_setexceptionports_np
917 * Description: Set a new port for a set of exception ports in the spawned task.
919 * Parameters: attr The spawn attributes object for the
921 * mask A bitfield indicating which exceptions
922 * to associate the port with
923 * new_port The new value for the exception port
924 * behavior The default behavior for the port
925 * flavor The default flavor for the port
926 * (see task_set_exception_ports)
931 posix_spawnattr_setexceptionports_np(
932 posix_spawnattr_t
*attr
,
933 exception_mask_t mask
,
934 mach_port_t new_port
,
935 exception_behavior_t behavior
,
936 thread_state_flavor_t flavor
)
938 _ps_port_action_t action
= {
939 .port_type
= PSPA_EXCEPTION
,
941 .new_port
= new_port
,
942 .behavior
= behavior
,
945 return posix_spawn_appendportaction_np(attr
, &action
);
949 * posix_spawnattr_setauditsessionport_np
951 * Description: Set the audit session port rights attribute in the spawned task.
952 * This is used to securely set the audit session information for
955 * Parameters: attr The spawn attributes object for the
957 * au_sessionport The audit session send port right
962 posix_spawnattr_setauditsessionport_np(
963 posix_spawnattr_t
*attr
,
964 mach_port_t au_sessionport
)
966 _ps_port_action_t action
= {
967 .port_type
= PSPA_AU_SESSION
,
968 .new_port
= au_sessionport
,
970 return posix_spawn_appendportaction_np(attr
, &action
);
975 * posix_spawn_file_actions_init
977 * Description: Initialize a spawn file actions object attr with default values
979 * Parameters: file_actions The spawn file actions object to be
983 * ENOMEM Insufficient memory exists to
984 * initialize the spawn file actions
987 * Note: As an implementation detail, the externally visibily type
988 * posix_spawn_file_actions_t is defined to be a void *, and
989 * initialization involves allocation of a memory object.
990 * Subsequent changes to the spawn file actions may result in
991 * reallocation under the covers.
993 * Reinitialization of an already initialized spawn file actions
994 * object will result in memory being leaked. Because spawn
995 * file actions are not required to be used in conjunction with a
996 * static initializer, there is no way to distinguish a spawn
997 * file actions with stack garbage from one that's been
998 * initialized. This is arguably an API design error.
1001 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
1003 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1006 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
1009 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
1010 (*psactsp
)->psfa_act_count
= 0;
1018 * posix_spawn_file_actions_destroy
1020 * Description: Destroy a spawn file actions object that was previously
1021 * initialized via posix_spawn_file_actions_init() by freeing any
1022 * memory associated with it and setting it to an invalid value.
1024 * Parameters: attr The spawn file actions object to be
1027 * Returns: 0 Success
1029 * Notes: The destroyed spawn file actions results in the void * pointer
1030 * being set to NULL; subsequent use without reinitialization
1031 * will result in explicit program failure (rather than merely
1032 * "undefined behaviour").
1034 * NOTIMP: Allowed failures (checking NOT required):
1035 * EINVAL The value specified by file_actions is invalid.
1038 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
1040 _posix_spawn_file_actions_t psacts
;
1042 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1046 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
1048 *file_actions
= NULL
;
1055 * _posix_spawn_file_actions_grow
1057 * Description: Grow the available list of file actions associated with the
1058 * pointer to the structure provided; replace the contents of the
1059 * pointer as a side effect.
1061 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
1064 * Returns: 0 Success
1065 * ENOMEM Insufficient memory for operation
1067 * Notes: This code is common to all posix_spawn_file_actions_*()
1068 * functions, since we use a naieve data structure implementation
1069 * at present. Future optimization will likely change this.
1072 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
1075 if (os_mul_overflow((*psactsp
)->psfa_act_alloc
, 2, &newnum
)) {
1079 size_t newsize
= PSF_ACTIONS_SIZE(newnum
);
1085 * XXX may want to impose an administrative limit here; POSIX does
1086 * XXX not provide for an administrative error return in this case,
1087 * XXX so it's probably acceptable to just fail catastrophically
1088 * XXX instead of implementing one.
1090 _posix_spawn_file_actions_t new_psacts
;
1091 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), newsize
)) == NULL
) {
1094 new_psacts
->psfa_act_alloc
= newnum
;
1095 *psactsp
= new_psacts
;
1102 * posix_spawn_file_actions_addopen
1104 * Description: Add an open action to the object referenced by 'file_actions'
1105 * that will cause the file named by 'path' to be attempted to be
1106 * opened with flags 'oflag' and mode 'mode', and, if successful,
1107 * return as descriptor 'filedes' to the spawned process.
1109 * Parameters: file_actions File action object to augment
1110 * filedes fd that open is to use
1111 * path path to file to open
1112 * oflag open file flags
1113 * mode open file mode
1115 * Returns: 0 Success
1116 * EBADF The value specified by fildes is
1117 * negative or greater than or equal to
1119 * ENOMEM Insufficient memory exists to add to
1120 * the spawn file actions object.
1122 * NOTIMP: Allowed failures (checking NOT required):
1123 * EINVAL The value specified by file_actions is invalid.
1126 posix_spawn_file_actions_addopen(
1127 posix_spawn_file_actions_t
* __restrict file_actions
,
1128 int filedes
, const char * __restrict path
, int oflag
,
1131 _posix_spawn_file_actions_t
*psactsp
;
1132 _psfa_action_t
*psfileact
;
1134 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1138 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1139 /* Range check; required by POSIX */
1140 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1144 /* If we do not have enough slots, grow the structure */
1145 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1146 /* need to grow file actions structure */
1147 if (_posix_spawn_file_actions_grow(psactsp
)) {
1153 * Allocate next available slot and fill it out
1155 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1157 psfileact
->psfaa_type
= PSFA_OPEN
;
1158 psfileact
->psfaa_filedes
= filedes
;
1159 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1160 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1161 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1168 * posix_spawn_file_actions_addclose
1170 * Description: Add a close action to the object referenced by 'file_actions'
1171 * that will cause the file referenced by 'filedes' to be
1172 * attempted to be closed in the spawned process.
1174 * Parameters: file_actions File action object to augment
1175 * filedes fd to close
1177 * Returns: 0 Success
1178 * EBADF The value specified by fildes is
1179 * negative or greater than or equal to
1181 * ENOMEM Insufficient memory exists to add to
1182 * the spawn file actions object.
1184 * NOTIMP: Allowed failures (checking NOT required):
1185 * EINVAL The value specified by file_actions is invalid.
1188 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1191 _posix_spawn_file_actions_t
*psactsp
;
1192 _psfa_action_t
*psfileact
;
1194 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1198 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1199 /* Range check; required by POSIX */
1200 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1204 /* If we do not have enough slots, grow the structure */
1205 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1206 /* need to grow file actions structure */
1207 if (_posix_spawn_file_actions_grow(psactsp
)) {
1213 * Allocate next available slot and fill it out
1215 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1217 psfileact
->psfaa_type
= PSFA_CLOSE
;
1218 psfileact
->psfaa_filedes
= filedes
;
1225 * posix_spawn_file_actions_adddup2
1227 * Description: Add a dup2 action to the object referenced by 'file_actions'
1228 * that will cause the file referenced by 'filedes' to be
1229 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1232 * Parameters: file_actions File action object to augment
1233 * filedes fd to dup2
1234 * newfiledes fd to dup2 it to
1236 * Returns: 0 Success
1237 * EBADF The value specified by either fildes
1238 * or by newfiledes is negative or greater
1239 * than or equal to {OPEN_MAX}.
1240 * ENOMEM Insufficient memory exists to add to
1241 * the spawn file actions object.
1243 * NOTIMP: Allowed failures (checking NOT required):
1244 * EINVAL The value specified by file_actions is invalid.
1247 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1248 int filedes
, int newfiledes
)
1250 _posix_spawn_file_actions_t
*psactsp
;
1251 _psfa_action_t
*psfileact
;
1253 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1257 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1258 /* Range check; required by POSIX */
1259 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1260 newfiledes
< 0 || newfiledes
>= OPEN_MAX
) {
1264 /* If we do not have enough slots, grow the structure */
1265 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1266 /* need to grow file actions structure */
1267 if (_posix_spawn_file_actions_grow(psactsp
)) {
1273 * Allocate next available slot and fill it out
1275 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1277 psfileact
->psfaa_type
= PSFA_DUP2
;
1278 psfileact
->psfaa_filedes
= filedes
;
1279 psfileact
->psfaa_openargs
.psfao_oflag
= newfiledes
;
1285 * posix_spawn_file_actions_addinherit_np
1287 * Description: Add the "inherit" action to the object referenced by
1288 * 'file_actions' that will cause the file referenced by
1289 * 'filedes' to continue to be available in the spawned
1290 * process via the same descriptor.
1292 * Inheritance is the normal default behaviour for
1293 * file descriptors across exec and spawn; but if the
1294 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1295 * default is reversed for the purposes of the spawn
1296 * invocation. Any pre-existing descriptors that
1297 * need to be made available to the spawned process can
1298 * be marked explicitly as 'inherit' via this interface.
1299 * Otherwise they will be automatically closed.
1301 * Note that any descriptors created via the other file
1302 * actions interfaces are automatically marked as 'inherit'.
1304 * Parameters: file_actions File action object to augment
1305 * filedes fd to inherit.
1307 * Returns: 0 Success
1308 * EBADF The value specified by fildes is
1309 * negative or greater than or equal to
1311 * ENOMEM Insufficient memory exists to add to
1312 * the spawn file actions object.
1314 * NOTIMP: Allowed failures (checking NOT required):
1315 * EINVAL The value specified by file_actions is invalid.
1318 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1321 _posix_spawn_file_actions_t
*psactsp
;
1322 _psfa_action_t
*psfileact
;
1324 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1328 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1329 /* Range check; required by POSIX */
1330 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1334 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1335 /* If we do not have enough slots, grow the structure */
1336 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1337 /* need to grow file actions structure */
1338 if (_posix_spawn_file_actions_grow(psactsp
)) {
1344 * Allocate next available slot and fill it out
1346 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1348 psfileact
->psfaa_type
= PSFA_INHERIT
;
1349 psfileact
->psfaa_filedes
= filedes
;
1355 posix_spawnattr_setcpumonitor_default(posix_spawnattr_t
* __restrict attr
)
1357 return posix_spawnattr_setcpumonitor(attr
, PROC_POLICY_CPUMON_DEFAULTS
, 0);
1361 posix_spawnattr_setcpumonitor(posix_spawnattr_t
* __restrict attr
,
1362 uint64_t percent
, uint64_t interval
)
1364 _posix_spawnattr_t psattr
;
1366 if (attr
== NULL
|| *attr
== NULL
) {
1370 psattr
= *(_posix_spawnattr_t
*)attr
;
1372 psattr
->psa_cpumonitor_percent
= percent
;
1373 psattr
->psa_cpumonitor_interval
= interval
;
1379 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1380 uint64_t *percent
, uint64_t *interval
)
1382 _posix_spawnattr_t psattr
;
1384 if (attr
== NULL
|| *attr
== NULL
) {
1388 psattr
= *(_posix_spawnattr_t
*)attr
;
1390 *percent
= psattr
->psa_cpumonitor_percent
;
1391 *interval
= psattr
->psa_cpumonitor_interval
;
1396 #if TARGET_OS_EMBEDDED
1398 * posix_spawnattr_setjetsam
1400 * Description: Set jetsam attributes for the spawn attribute object
1401 * referred to by 'attr'.
1403 * Parameters: flags The flags value to set
1404 * priority Relative jetsam priority
1405 * memlimit Value in megabytes; a memory footprint
1406 * above this level may result in termination.
1407 * Implies both active and inactive limits.
1409 * Returns: 0 Success
1411 * Note: to be deprecated (not available on desktop)
1415 posix_spawnattr_setjetsam(posix_spawnattr_t
* __restrict attr
,
1416 short flags
, int priority
, int memlimit
)
1418 short flags_ext
= flags
;
1420 if (flags
& POSIX_SPAWN_JETSAM_MEMLIMIT_FATAL
) {
1421 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1422 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1424 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1425 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1428 return posix_spawnattr_setjetsam_ext(attr
, flags_ext
, priority
, memlimit
, memlimit
);
1430 #endif /* TARGET_OS_EMBEDDED */
1433 * posix_spawnattr_setjetsam_ext
1435 * Description: Set jetsam attributes for the spawn attribute object
1436 * referred to by 'attr'.
1438 * Parameters: flags The flags value to set
1439 * priority Relative jetsam priority
1440 * memlimit_active Value in megabytes; memory footprint
1441 * above this level while process is
1442 * active may result in termination.
1443 * memlimit_inactive Value in megabytes; memory footprint
1444 * above this level while process is
1445 * inactive may result in termination.
1447 * Returns: 0 Success
1450 posix_spawnattr_setjetsam_ext(posix_spawnattr_t
* __restrict attr
,
1451 short flags
, int priority
, int memlimit_active
, int memlimit_inactive
)
1453 _posix_spawnattr_t psattr
;
1455 if (attr
== NULL
|| *attr
== NULL
) {
1459 psattr
= *(_posix_spawnattr_t
*)attr
;
1461 psattr
->psa_jetsam_flags
= flags
;
1462 psattr
->psa_jetsam_flags
|= POSIX_SPAWN_JETSAM_SET
;
1463 psattr
->psa_priority
= priority
;
1464 psattr
->psa_memlimit_active
= memlimit_active
;
1465 psattr
->psa_memlimit_inactive
= memlimit_inactive
;
1471 posix_spawnattr_set_threadlimit_ext(posix_spawnattr_t
* __restrict attr
,
1474 _posix_spawnattr_t psattr
;
1476 if (attr
== NULL
|| *attr
== NULL
) {
1480 psattr
= *(_posix_spawnattr_t
*)attr
;
1482 psattr
->psa_thread_limit
= thread_limit
;
1489 * posix_spawnattr_set_importancewatch_port_np
1491 * Description: Mark ports referred to by these rights
1492 * to boost the new task instead of their current task
1493 * for the spawn attribute object referred to by 'attr'.
1494 * Ports must be valid at posix_spawn time. They will NOT be
1495 * consumed by the kernel, so they must be deallocated after the spawn returns.
1496 * (If you are SETEXEC-ing, they are cleaned up by the exec operation).
1498 * The maximum number of watch ports allowed is defined by POSIX_SPAWN_IMPORTANCE_PORT_COUNT.
1500 * Parameters: count Number of ports in portarray
1501 * portarray Array of rights
1503 * Returns: 0 Success
1504 * EINVAL Bad port count
1505 * ENOMEM Insufficient memory exists to add to
1506 * the spawn port actions object.
1509 posix_spawnattr_set_importancewatch_port_np(posix_spawnattr_t
* __restrict attr
,
1510 int count
, mach_port_t portarray
[])
1514 if (count
< 0 || count
> POSIX_SPAWN_IMPORTANCE_PORT_COUNT
) {
1518 for (i
= 0; i
< count
; i
++) {
1519 _ps_port_action_t action
= {
1520 .port_type
= PSPA_IMP_WATCHPORTS
,
1521 .new_port
= portarray
[i
],
1523 int err
= posix_spawn_appendportaction_np(attr
, &action
);
1534 _ps_mac_policy_extension_t
*
1535 posix_spawnattr_macpolicyinfo_lookup(_posix_spawn_mac_policy_extensions_t psmx
, const char *policyname
)
1543 for (i
= 0; i
< psmx
->psmx_count
; i
++) {
1544 _ps_mac_policy_extension_t
*extension
= &psmx
->psmx_extensions
[i
];
1545 if (strcmp(extension
->policyname
, policyname
) == 0) {
1553 posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t
* __restrict attr
,
1554 const char *policyname
, void **datap
, size_t *datalenp
)
1556 _posix_spawnattr_t psattr
;
1557 _ps_mac_policy_extension_t
*extension
;
1559 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
|| datap
== NULL
) {
1563 psattr
= *(_posix_spawnattr_t
*)attr
;
1564 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1565 if (extension
== NULL
) {
1568 *datap
= (void *)(uintptr_t)extension
->data
;
1569 if (datalenp
!= NULL
) {
1570 *datalenp
= (size_t)extension
->datalen
;
1576 posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t
* __restrict attr
,
1577 const char *policyname
, void *data
, size_t datalen
)
1579 _posix_spawnattr_t psattr
;
1580 _posix_spawn_mac_policy_extensions_t psmx
;
1581 _ps_mac_policy_extension_t
*extension
;
1583 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
) {
1587 psattr
= *(_posix_spawnattr_t
*)attr
;
1588 psmx
= psattr
->psa_mac_extensions
;
1589 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1590 if (extension
!= NULL
) {
1591 extension
->data
= (uintptr_t)data
;
1592 extension
->datalen
= datalen
;
1594 } else if (psmx
== NULL
) {
1595 psmx
= psattr
->psa_mac_extensions
= malloc(PS_MAC_EXTENSIONS_SIZE(PS_MAC_EXTENSIONS_INIT_COUNT
));
1599 psmx
->psmx_alloc
= PS_MAC_EXTENSIONS_INIT_COUNT
;
1600 psmx
->psmx_count
= 0;
1601 } else if (psmx
->psmx_count
== psmx
->psmx_alloc
) {
1603 if (os_mul_overflow(psmx
->psmx_alloc
, 2, &newnum
)) {
1606 size_t extsize
= PS_MAC_EXTENSIONS_SIZE(newnum
);
1610 psmx
= psattr
->psa_mac_extensions
= reallocf(psmx
, extsize
);
1614 psmx
->psmx_alloc
= newnum
;
1616 extension
= &psmx
->psmx_extensions
[psmx
->psmx_count
];
1617 strlcpy(extension
->policyname
, policyname
, sizeof(extension
->policyname
));
1618 extension
->data
= (uintptr_t)data
;
1619 extension
->datalen
= datalen
;
1620 psmx
->psmx_count
+= 1;
1625 posix_spawnattr_setcoalition_np(const posix_spawnattr_t
* __restrict attr
,
1626 uint64_t coalitionid
, int type
, int role
)
1628 _posix_spawnattr_t psattr
;
1629 struct _posix_spawn_coalition_info
*coal_info
;
1631 if (attr
== NULL
|| *attr
== NULL
) {
1634 if (type
< 0 || type
> COALITION_TYPE_MAX
) {
1638 psattr
= *(_posix_spawnattr_t
*)attr
;
1640 coal_info
= psattr
->psa_coalition_info
;
1642 coal_info
= (struct _posix_spawn_coalition_info
*)malloc(sizeof(*coal_info
));
1646 memset(coal_info
, 0, sizeof(*coal_info
));
1647 psattr
->psa_coalition_info
= coal_info
;
1650 coal_info
->psci_info
[type
].psci_id
= coalitionid
;
1651 coal_info
->psci_info
[type
].psci_role
= role
;
1658 posix_spawnattr_set_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t qos_clamp
)
1660 _posix_spawnattr_t psattr
;
1662 if (attr
== NULL
|| *attr
== NULL
) {
1666 if (qos_clamp
>= POSIX_SPAWN_PROC_CLAMP_LAST
) {
1670 psattr
= *(_posix_spawnattr_t
*)attr
;
1671 psattr
->psa_qos_clamp
= qos_clamp
;
1677 posix_spawnattr_get_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict qos_clampp
)
1679 _posix_spawnattr_t psattr
;
1681 if (attr
== NULL
|| *attr
== NULL
) {
1685 psattr
= *(_posix_spawnattr_t
*)attr
;
1686 *qos_clampp
= psattr
->psa_qos_clamp
;
1692 posix_spawnattr_set_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t darwin_role
)
1694 _posix_spawnattr_t psattr
;
1696 if (attr
== NULL
|| *attr
== NULL
) {
1700 psattr
= *(_posix_spawnattr_t
*)attr
;
1701 psattr
->psa_darwin_role
= darwin_role
;
1707 posix_spawnattr_get_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict darwin_rolep
)
1709 _posix_spawnattr_t psattr
;
1711 if (attr
== NULL
|| *attr
== NULL
) {
1715 psattr
= *(_posix_spawnattr_t
*)attr
;
1716 *darwin_rolep
= psattr
->psa_darwin_role
;
1723 posix_spawnattr_set_persona_np(const posix_spawnattr_t
* __restrict attr
, uid_t persona_id
, uint32_t flags
)
1725 _posix_spawnattr_t psattr
;
1726 struct _posix_spawn_persona_info
*persona
;
1728 if (attr
== NULL
|| *attr
== NULL
) {
1732 if (flags
& ~POSIX_SPAWN_PERSONA_ALL_FLAGS
) {
1736 psattr
= *(_posix_spawnattr_t
*)attr
;
1738 persona
= psattr
->psa_persona_info
;
1740 persona
= (struct _posix_spawn_persona_info
*)malloc(sizeof(*persona
));
1744 persona
->pspi_uid
= 0;
1745 persona
->pspi_gid
= 0;
1746 persona
->pspi_ngroups
= 0;
1747 persona
->pspi_groups
[0] = 0;
1749 psattr
->psa_persona_info
= persona
;
1752 persona
->pspi_id
= persona_id
;
1753 persona
->pspi_flags
= flags
;
1759 posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t
* __restrict attr
, uid_t uid
)
1761 _posix_spawnattr_t psattr
;
1762 struct _posix_spawn_persona_info
*persona
;
1764 if (attr
== NULL
|| *attr
== NULL
) {
1768 psattr
= *(_posix_spawnattr_t
*)attr
;
1769 persona
= psattr
->psa_persona_info
;
1774 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
1778 persona
->pspi_uid
= uid
;
1780 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_UID
;
1786 posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t
* __restrict attr
, gid_t gid
)
1788 _posix_spawnattr_t psattr
;
1789 struct _posix_spawn_persona_info
*persona
;
1791 if (attr
== NULL
|| *attr
== NULL
) {
1795 psattr
= *(_posix_spawnattr_t
*)attr
;
1796 persona
= psattr
->psa_persona_info
;
1801 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
1805 persona
->pspi_gid
= gid
;
1807 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GID
;
1813 posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t
* __restrict attr
, int ngroups
, gid_t
*gidarray
, uid_t gmuid
)
1815 _posix_spawnattr_t psattr
;
1816 struct _posix_spawn_persona_info
*persona
;
1818 if (attr
== NULL
|| *attr
== NULL
) {
1822 if (gidarray
== NULL
) {
1826 if (ngroups
> NGROUPS
|| ngroups
< 0) {
1830 psattr
= *(_posix_spawnattr_t
*)attr
;
1831 persona
= psattr
->psa_persona_info
;
1836 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
1840 persona
->pspi_ngroups
= ngroups
;
1841 for (int i
= 0; i
< ngroups
; i
++) {
1842 persona
->pspi_groups
[i
] = gidarray
[i
];
1845 persona
->pspi_gmuid
= gmuid
;
1847 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GROUPS
;
1853 posix_spawnattr_set_max_addr_np(const posix_spawnattr_t
* __restrict attr
, uint64_t max_addr
)
1855 _posix_spawnattr_t psattr
;
1857 if (attr
== NULL
|| *attr
== NULL
) {
1861 psattr
= *(_posix_spawnattr_t
*)attr
;
1862 psattr
->psa_max_addr
= max_addr
;
1870 * Description: Create a new process from the process image corresponding to
1871 * the supplied 'path' argument.
1873 * Parameters: pid Pointer to pid_t to receive the
1874 * PID of the spawned process, if
1875 * successful and 'pid' != NULL
1876 * path Path of image file to spawn
1877 * file_actions spawn file actions object which
1878 * describes file actions to be
1879 * performed during the spawn
1880 * attrp spawn attributes object which
1881 * describes attributes to be
1882 * applied during the spawn
1883 * argv argument vector array; NULL
1885 * envp environment vector array; NULL
1888 * Returns: 0 Success
1889 * !0 An errno value indicating the
1890 * cause of the failure to spawn
1892 * Notes: Unlike other system calls, the return value of this system
1893 * call is expected to either be a 0 or an errno, rather than a
1894 * 0 or a -1, with the 'errno' variable being set.
1896 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
1897 struct _posix_spawn_args_desc
*,
1898 char *const argv
[__restrict
], char *const envp
[__restrict
]);
1901 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
1902 const posix_spawn_file_actions_t
*file_actions
,
1903 const posix_spawnattr_t
* __restrict attrp
,
1904 char *const argv
[__restrict
], char *const envp
[__restrict
])
1906 int saveerrno
= errno
;
1909 * Only do extra work if we have file actions or attributes to push
1910 * down. We use a descriptor to push this information down, since we
1911 * want to have size information, which will let us (1) preallocate a
1912 * single chunk of memory for the copyin(), and (2) allow us to do a
1913 * single copyin() per attributes or file actions as a monlithic block.
1915 * Note: A future implementation may attempt to do the same
1916 * thing for the argv/envp data, which could potentially
1917 * result in a performance improvement due to increased
1918 * kernel efficiency, even though it would mean copying
1919 * the data in user space.
1921 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
1922 struct _posix_spawn_args_desc ad
;
1924 memset(&ad
, 0, sizeof(ad
));
1925 if (attrp
!= NULL
&& *attrp
!= NULL
) {
1926 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
1927 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
1930 if (psattr
->psa_ports
!= NULL
) {
1931 size_t psact_size
= PS_PORT_ACTIONS_SIZE(psattr
->psa_ports
->pspa_count
);
1932 if (psact_size
== 0 && psattr
->psa_ports
->pspa_count
!= 0) {
1937 ad
.port_actions
= psattr
->psa_ports
;
1938 ad
.port_actions_size
= psact_size
;
1940 if (psattr
->psa_mac_extensions
!= NULL
) {
1941 size_t macext_size
= PS_MAC_EXTENSIONS_SIZE(psattr
->psa_mac_extensions
->psmx_count
);
1942 if (macext_size
== 0 && psattr
->psa_mac_extensions
->psmx_count
!= 0) {
1947 ad
.mac_extensions
= psattr
->psa_mac_extensions
;
1948 ad
.mac_extensions_size
= macext_size
;
1950 if (psattr
->psa_coalition_info
!= NULL
) {
1951 ad
.coal_info_size
= sizeof(struct _posix_spawn_coalition_info
);
1952 ad
.coal_info
= psattr
->psa_coalition_info
;
1954 if (psattr
->psa_persona_info
!= NULL
) {
1955 ad
.persona_info_size
= sizeof(struct _posix_spawn_persona_info
);
1956 ad
.persona_info
= psattr
->psa_persona_info
;
1959 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
1960 _posix_spawn_file_actions_t psactsp
=
1961 *(_posix_spawn_file_actions_t
*)file_actions
;
1963 if (psactsp
->psfa_act_count
> 0) {
1964 size_t fa_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
1965 if (fa_size
== 0 && psactsp
->psfa_act_count
!= 0) {
1970 ad
.file_actions_size
= fa_size
;
1971 ad
.file_actions
= psactsp
;
1975 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
1977 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);