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