xref: /illumos-gate/usr/src/uts/common/sys/spawn_impl.h (revision ac2250cb76bb32944fd2c8a3ba2cd3f79747748d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright (c) 2011 by Delphix. All rights reserved.
29  * Copyright 2026 Oxide Computer Company
30  */
31 
32 #ifndef _SYS_SPAWN_IMPL_H
33 #define	_SYS_SPAWN_IMPL_H
34 
35 /*
36  * Private interface between libc and the kernel for the spawn(2) system
37  * call that implements the posix_spawn(3C) family. libc marshals an entire
38  * spawn - the attributes, file actions, argv and envp - into the structures
39  * defined here, and the kernel parses them back out. None of it is a
40  * committed interface and it is not packaged, so both sides can change in
41  * lockstep. The public, application-visible posix_spawn definitions live in
42  * <sys/spawn.h>.
43  */
44 
45 #include <sys/types.h>
46 #include <sys/debug.h>
47 #include <sys/stdbool.h>
48 #include <sys/stdalign.h>
49 #include <sys/priocntl.h>
50 
51 #ifdef	__cplusplus
52 extern "C" {
53 #endif
54 
55 #define	ALL_POSIX_SPAWN_FLAGS			\
56 		(POSIX_SPAWN_RESETIDS |		\
57 		POSIX_SPAWN_SETPGROUP |		\
58 		POSIX_SPAWN_SETSIGDEF |		\
59 		POSIX_SPAWN_SETSIGMASK |	\
60 		POSIX_SPAWN_SETSCHEDPARAM |	\
61 		POSIX_SPAWN_SETSCHEDULER |	\
62 		POSIX_SPAWN_SETSID |		\
63 		POSIX_SPAWN_SETSIGIGN_NP |	\
64 		POSIX_SPAWN_NOSIGCHLD_NP |	\
65 		POSIX_SPAWN_WAITPID_NP |	\
66 		POSIX_SPAWN_NOEXECERR_NP)
67 
68 /*
69  * The exit status of a spawned child whose exec failed while
70  * POSIX_SPAWN_NOEXECERR_NP was in effect, following the shell convention
71  * for a command that was found but could not be executed.
72  */
73 #define	SPAWN_NOEXECERR_STATUS	127
74 
75 /*
76  * Ensure that this struct retains the same layout in both 32- and 64-bit
77  * binaries. It is passed to the kernel via spawn(2).
78  */
79 typedef struct {
80 	int		sa_psflags;	/* POSIX_SPAWN_* flags */
81 	int		sa_priority;
82 	int		sa_schedpolicy;
83 	pid_t		sa_pgroup;
84 	sigset_t	sa_sigdefault;
85 	sigset_t	sa_sigignore;
86 	sigset_t	sa_sigmask;
87 } spawn_attr_t;
88 CTASSERT(sizeof (spawn_attr_t) == 64);
89 CTASSERT(alignof (spawn_attr_t) <= sizeof (uint32_t));
90 
91 typedef enum file_action {
92 	FA_OPEN,
93 	FA_CLOSE,
94 	FA_DUP2,
95 	FA_CLOSEFROM,
96 	FA_CHDIR,
97 	FA_FCHDIR
98 } file_action_t;
99 
100 /*
101  * The scheduling attributes, as resolved by libc into the form that the
102  * kernel child applies directly to itself. This struct has the same layout
103  * in both 32- and 64-bit code.
104  */
105 typedef enum kspawn_sched_op {
106 	KSCHED_PARMS = 1,
107 	KSCHED_PRIO
108 } kspawn_sched_op_t;
109 
110 typedef struct kspawn_sched {
111 	kspawn_sched_op_t	ksched_op;
112 	union {
113 		pcparms_t	u_parms;
114 		pcprio_t	u_prio;
115 	} ksched_u;
116 } kspawn_sched_t;
117 CTASSERT(sizeof (kspawn_sched_t) == 40);
118 CTASSERT(alignof (kspawn_sched_t) <= sizeof (uint32_t));
119 
120 #define	ksched_parms	ksched_u.u_parms
121 #define	ksched_prio	ksched_u.u_prio
122 
123 typedef struct file_attr {
124 	struct file_attr *fa_next;	/* circular list of file actions */
125 	struct file_attr *fa_prev;
126 	file_action_t	fa_type;	/* type of action */
127 	char		*fa_path;	/* copied pathname for open() */
128 	uint_t		fa_pathsize;	/* size of fa_path[] array */
129 	int		fa_oflag;	/* oflag for open() */
130 	mode_t		fa_mode;	/* mode for open() */
131 	int		fa_filedes;	/* file descriptor for open()/close() */
132 	int		fa_newfiledes;	/* new file descriptor for dup2() */
133 } file_attr_t;
134 
135 /*
136  * We need to marshal all of the data that spawn(2) needs. We could pass
137  * the spawn_attr_t directly but the set of file actions needs to be packed
138  * into something that the kernel can quickly copy in and parse. There are
139  * additional data items too such as the shell and PATH to use for
140  * posix_spawnp(). We therefore pack everything into a new structure -
141  * spawn_param_t. The following structures have the same layout in both 32-
142  * and 64-bit code. Every *_off field is a byte offset measured from the start
143  * of the trailing sp_data[]/sa_data[] array.
144  */
145 typedef struct kfile_attr {
146 	uint32_t	kfa_len;	/* size of this record */
147 	file_action_t	kfa_type;	/* type of action */
148 	uint32_t	kfa_pathsize;	/* size of fa_path[] array (can be 0) */
149 	uint32_t	kfa_oflag;	/* oflag for open() */
150 	uint32_t	kfa_mode;	/* mode for open() */
151 	int32_t		kfa_filedes;	/* file descriptor for open()/close() */
152 	int32_t		kfa_newfiledes;	/* new file descriptor for dup2() */
153 	char		kfa_path[];	/* pathname for open()/chdir() */
154 } kfile_attr_t;
155 CTASSERT(sizeof (kfile_attr_t) == 28);
156 CTASSERT(alignof (kfile_attr_t) <= sizeof (uint32_t));
157 
158 typedef struct spawn_param {
159 	uint32_t	sp_size;
160 	uint32_t	sp_datalen;
161 	uint32_t	sp_attr_off;	/* Offset of spawn_attr_t */
162 	uint32_t	sp_attr_len;	/* Length of spawn_attr_t */
163 	uint32_t	sp_fattr_off;	/* Offset of the first file attribute */
164 	uint32_t	sp_fattr_cnt;	/* Number of file attributes */
165 	uint32_t	sp_shell_off;	/* Offset of the shell */
166 	uint32_t	sp_shell_len;	/* Length of the shell */
167 	uint32_t	sp_path_off;	/* Offset of the PATH */
168 	uint32_t	sp_path_len;	/* Length of the PATH */
169 	uint32_t	sp_sched_off;	/* Offset of kspawn_sched_t */
170 	uint32_t	sp_sched_len;	/* Length of kspawn_sched_t */
171 	uint8_t		sp_data[];
172 } spawn_param_t;
173 CTASSERT(sizeof (spawn_param_t) == 48);
174 
175 typedef struct spawn_args {
176 	uint32_t	sa_size;
177 	uint32_t	sa_datalen;
178 	uint32_t	sa_arg_off;	/* Offset of first argument */
179 	uint32_t	sa_arg_cnt;	/* Number of arguments */
180 	uint32_t	sa_env_off;	/* Offset of first environment entry */
181 	uint32_t	sa_env_cnt;	/* Number of environment entries */
182 	uint8_t		sa_data[];
183 } spawn_args_t;
184 CTASSERT(sizeof (spawn_args_t) == 24);
185 
186 #ifdef _KERNEL
187 
188 #include <sys/model.h>
189 #include <sys/vnode.h>
190 
191 typedef struct kspawn_param {
192 	/*
193 	 * The parent/child handshake. The child sets ksp_complete (with
194 	 * ksp_error) under ksp_lock once it has applied the spawn and tried
195 	 * the exec, then signals ksp_cv to wake the waiting parent.
196 	 */
197 	bool		ksp_complete;
198 	int		ksp_error;
199 	kmutex_t	ksp_lock;
200 	kcondvar_t	ksp_cv;
201 	/*
202 	 * On entry, the program path copied in from the caller. On success,
203 	 * the path the child actually exec'd, which for posix_spawnp() or the
204 	 * shell fallback may differ. Audited by the parent.
205 	 */
206 	char		ksp_path[MAXPATHLEN];
207 	/*
208 	 * Whether to gather the audit detail below. The parent sets it from
209 	 * its own audit state before the child runs. The child cannot test
210 	 * its own, since exec resets the per-thread audit flag.
211 	 */
212 	bool		ksp_audit;
213 	/*
214 	 * Attributes of the exec'd file, for the audit attribute token.
215 	 */
216 	struct vattr	ksp_vattr;
217 	bool		ksp_have_vattr;
218 	/*
219 	 * When non-NULL, the exact vector the child exec'd, as ksp_argc
220 	 * NUL-terminated strings; audited in place of the caller's argv,
221 	 * which it matches except for the shell fallback. The parent frees it.
222 	 */
223 	char		*ksp_argv;
224 	uint_t		ksp_argc;
225 	size_t		ksp_argvsz;
226 	/*
227 	 * Marshalled spawn attributes and file actions to apply.
228 	 */
229 	spawn_param_t	*ksp_param;
230 	/*
231 	 * Marshalled argument and environment vectors for exec.
232 	 */
233 	spawn_args_t	*ksp_args;
234 	/*
235 	 * Data model of the parent, used to read the marshalled data.
236 	 */
237 	model_t		ksp_parent_model;
238 	/*
239 	 * Lowest fd named by a closefrom() action, or INT_MAX if none. Set
240 	 * rom pre-scanning the file actions. The child copies the parent's fd
241 	 * table only below this.
242 	 */
243 	int		ksp_closefrom;
244 	/*
245 	 * Source fds of dup2/fchdir actions which must survive the fd-table
246 	 * copy even when they lie at or above ksp_closefrom.
247 	 */
248 	int		*ksp_reffds;
249 	uint_t		ksp_nreffds;
250 } kspawn_param_t;
251 
252 extern void spawn_main(void *);
253 extern void spawn_complete(kspawn_param_t *, int);
254 
255 #endif
256 
257 #ifdef	__cplusplus
258 }
259 #endif
260 
261 #endif	/* _SYS_SPAWN_IMPL_H */
262