Fri Feb 21 08:11:59 2014 UTC ()
Revert rev1.38. The header already begins with EXEC_SCRIPT_MAGIC="#!".
So it can't be ELFMAG="\177ELF" at the same time.

ok christos@


(maxv)
diff -r1.68 -r1.69 src/sys/kern/exec_script.c

cvs diff -r1.68 -r1.69 src/sys/kern/exec_script.c (switch to unified diff)

--- src/sys/kern/exec_script.c 2014/02/17 19:29:46 1.68
+++ src/sys/kern/exec_script.c 2014/02/21 08:11:59 1.69
@@ -1,373 +1,366 @@ @@ -1,373 +1,366 @@
1/* $NetBSD: exec_script.c,v 1.68 2014/02/17 19:29:46 maxv Exp $ */ 1/* $NetBSD: exec_script.c,v 1.69 2014/02/21 08:11:59 maxv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou 4 * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 16 * must display the following acknowledgement:
17 * This product includes software developed by Christopher G. Demetriou. 17 * This product includes software developed by Christopher G. Demetriou.
18 * 4. The name of the author may not be used to endorse or promote products 18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission 19 * derived from this software without specific prior written permission
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: exec_script.c,v 1.68 2014/02/17 19:29:46 maxv Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: exec_script.c,v 1.69 2014/02/21 08:11:59 maxv Exp $");
35 35
36#if defined(SETUIDSCRIPTS) && !defined(FDSCRIPTS) 36#if defined(SETUIDSCRIPTS) && !defined(FDSCRIPTS)
37#define FDSCRIPTS /* Need this for safe set-id scripts. */ 37#define FDSCRIPTS /* Need this for safe set-id scripts. */
38#endif 38#endif
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/systm.h> 41#include <sys/systm.h>
42#include <sys/proc.h> 42#include <sys/proc.h>
43#include <sys/kmem.h> 43#include <sys/kmem.h>
44#include <sys/vnode.h> 44#include <sys/vnode.h>
45#include <sys/namei.h> 45#include <sys/namei.h>
46#include <sys/file.h> 46#include <sys/file.h>
47#ifdef SETUIDSCRIPTS 47#ifdef SETUIDSCRIPTS
48#include <sys/stat.h> 48#include <sys/stat.h>
49#endif 49#endif
50#include <sys/filedesc.h> 50#include <sys/filedesc.h>
51#include <sys/exec.h> 51#include <sys/exec.h>
52#include <sys/resourcevar.h> 52#include <sys/resourcevar.h>
53#include <sys/module.h> 53#include <sys/module.h>
54#include <sys/exec_script.h> 54#include <sys/exec_script.h>
55#include <sys/exec_elf.h> 55#include <sys/exec_elf.h>
56 56
57MODULE(MODULE_CLASS_EXEC, exec_script, NULL); 57MODULE(MODULE_CLASS_EXEC, exec_script, NULL);
58 58
59static struct execsw exec_script_execsw[] = { 59static struct execsw exec_script_execsw[] = {
60 { SCRIPT_HDR_SIZE, 60 { SCRIPT_HDR_SIZE,
61 exec_script_makecmds, 61 exec_script_makecmds,
62 { NULL }, 62 { NULL },
63 NULL, 63 NULL,
64 EXECSW_PRIO_ANY, 64 EXECSW_PRIO_ANY,
65 0, 65 0,
66 NULL, 66 NULL,
67 NULL, 67 NULL,
68 NULL, 68 NULL,
69 exec_setup_stack }, 69 exec_setup_stack },
70}; 70};
71 71
72static int 72static int
73exec_script_modcmd(modcmd_t cmd, void *arg) 73exec_script_modcmd(modcmd_t cmd, void *arg)
74{ 74{
75 75
76 switch (cmd) { 76 switch (cmd) {
77 case MODULE_CMD_INIT: 77 case MODULE_CMD_INIT:
78 return exec_add(exec_script_execsw, 78 return exec_add(exec_script_execsw,
79 __arraycount(exec_script_execsw)); 79 __arraycount(exec_script_execsw));
80 80
81 case MODULE_CMD_FINI: 81 case MODULE_CMD_FINI:
82 return exec_remove(exec_script_execsw, 82 return exec_remove(exec_script_execsw,
83 __arraycount(exec_script_execsw)); 83 __arraycount(exec_script_execsw));
84 84
85 case MODULE_CMD_AUTOUNLOAD: 85 case MODULE_CMD_AUTOUNLOAD:
86 /* 86 /*
87 * We don't want to be autounloaded because our use is 87 * We don't want to be autounloaded because our use is
88 * transient: no executables with p_execsw equal to 88 * transient: no executables with p_execsw equal to
89 * exec_script_execsw will exist, so FINI will never 89 * exec_script_execsw will exist, so FINI will never
90 * return EBUSY. However, the system will run scripts 90 * return EBUSY. However, the system will run scripts
91 * often. Return EBUSY here to prevent this module from 91 * often. Return EBUSY here to prevent this module from
92 * ping-ponging in and out of the kernel. 92 * ping-ponging in and out of the kernel.
93 */ 93 */
94 return EBUSY; 94 return EBUSY;
95 95
96 default: 96 default:
97 return ENOTTY; 97 return ENOTTY;
98 } 98 }
99} 99}
100 100
101/* 101/*
102 * exec_script_makecmds(): Check if it's an executable shell script. 102 * exec_script_makecmds(): Check if it's an executable shell script.
103 * 103 *
104 * Given a proc pointer and an exec package pointer, see if the referent 104 * Given a proc pointer and an exec package pointer, see if the referent
105 * of the epp is in shell script. If it is, then set thing up so that 105 * of the epp is in shell script. If it is, then set thing up so that
106 * the script can be run. This involves preparing the address space 106 * the script can be run. This involves preparing the address space
107 * and arguments for the shell which will run the script. 107 * and arguments for the shell which will run the script.
108 * 108 *
109 * This function is ultimately responsible for creating a set of vmcmds 109 * This function is ultimately responsible for creating a set of vmcmds
110 * which can be used to build the process's vm space and inserting them 110 * which can be used to build the process's vm space and inserting them
111 * into the exec package. 111 * into the exec package.
112 */ 112 */
113int 113int
114exec_script_makecmds(struct lwp *l, struct exec_package *epp) 114exec_script_makecmds(struct lwp *l, struct exec_package *epp)
115{ 115{
116 int error, hdrlinelen, shellnamelen, shellarglen; 116 int error, hdrlinelen, shellnamelen, shellarglen;
117 char *hdrstr = epp->ep_hdr; 117 char *hdrstr = epp->ep_hdr;
118 char *cp, *shellname, *shellarg; 118 char *cp, *shellname, *shellarg;
119 size_t shellargp_len; 119 size_t shellargp_len;
120 struct exec_fakearg *shellargp; 120 struct exec_fakearg *shellargp;
121 struct exec_fakearg *tmpsap; 121 struct exec_fakearg *tmpsap;
122 struct pathbuf *shell_pathbuf; 122 struct pathbuf *shell_pathbuf;
123 struct vnode *scriptvp; 123 struct vnode *scriptvp;
124#ifdef SETUIDSCRIPTS 124#ifdef SETUIDSCRIPTS
125 /* Gcc needs those initialized for spurious uninitialized warning */ 125 /* Gcc needs those initialized for spurious uninitialized warning */
126 uid_t script_uid = (uid_t) -1; 126 uid_t script_uid = (uid_t) -1;
127 gid_t script_gid = NOGROUP; 127 gid_t script_gid = NOGROUP;
128 u_short script_sbits; 128 u_short script_sbits;
129#endif 129#endif
130 130
131 /* 131 /*
132 * if the magic isn't that of a shell script, or we've already 132 * if the magic isn't that of a shell script, or we've already
133 * done shell script processing for this exec, punt on it. 133 * done shell script processing for this exec, punt on it.
134 */ 134 */
135 if ((epp->ep_flags & EXEC_INDIR) != 0 || 135 if ((epp->ep_flags & EXEC_INDIR) != 0 ||
136 epp->ep_hdrvalid < EXEC_SCRIPT_MAGICLEN || 136 epp->ep_hdrvalid < EXEC_SCRIPT_MAGICLEN ||
137 strncmp(hdrstr, EXEC_SCRIPT_MAGIC, EXEC_SCRIPT_MAGICLEN)) 137 strncmp(hdrstr, EXEC_SCRIPT_MAGIC, EXEC_SCRIPT_MAGICLEN))
138 return ENOEXEC; 138 return ENOEXEC;
139 139
140 /* 140 /*
141 * check that the shell spec is terminated by a newline, 141 * check that the shell spec is terminated by a newline,
142 * and that it isn't too large. Don't modify the 142 * and that it isn't too large. Don't modify the
143 * buffer unless we're ready to commit to handling it. 143 * buffer unless we're ready to commit to handling it.
144 * (The latter requirement means that we have to check 144 * (The latter requirement means that we have to check
145 * for both spaces and tabs later on.) 145 * for both spaces and tabs later on.)
146 */ 146 */
147 hdrlinelen = min(epp->ep_hdrvalid, SCRIPT_HDR_SIZE); 147 hdrlinelen = min(epp->ep_hdrvalid, SCRIPT_HDR_SIZE);
148 for (cp = hdrstr + EXEC_SCRIPT_MAGICLEN; cp < hdrstr + hdrlinelen; 148 for (cp = hdrstr + EXEC_SCRIPT_MAGICLEN; cp < hdrstr + hdrlinelen;
149 cp++) { 149 cp++) {
150 if (*cp == '\n') { 150 if (*cp == '\n') {
151 *cp = '\0'; 151 *cp = '\0';
152 break; 152 break;
153 } 153 }
154 } 154 }
155 if (cp >= hdrstr + hdrlinelen) 155 if (cp >= hdrstr + hdrlinelen)
156 return ENOEXEC; 156 return ENOEXEC;
157 157
158 /* 
159 * If the script has an ELF header, don't exec it. 
160 */ 
161 if (epp->ep_hdrvalid >= sizeof(ELFMAG)-1 && 
162 memcmp(hdrstr, ELFMAG, sizeof(ELFMAG)-1) == 0) 
163 return ENOEXEC; 
164 
165 shellname = NULL; 158 shellname = NULL;
166 shellarg = NULL; 159 shellarg = NULL;
167 shellarglen = 0; 160 shellarglen = 0;
168 161
169 /* strip spaces before the shell name */ 162 /* strip spaces before the shell name */
170 for (cp = hdrstr + EXEC_SCRIPT_MAGICLEN; *cp == ' ' || *cp == '\t'; 163 for (cp = hdrstr + EXEC_SCRIPT_MAGICLEN; *cp == ' ' || *cp == '\t';
171 cp++) 164 cp++)
172 ; 165 ;
173 166
174 /* collect the shell name; remember it's length for later */ 167 /* collect the shell name; remember it's length for later */
175 shellname = cp; 168 shellname = cp;
176 shellnamelen = 0; 169 shellnamelen = 0;
177 if (*cp == '\0') 170 if (*cp == '\0')
178 goto check_shell; 171 goto check_shell;
179 for ( /* cp = cp */ ; *cp != '\0' && *cp != ' ' && *cp != '\t'; cp++) 172 for ( /* cp = cp */ ; *cp != '\0' && *cp != ' ' && *cp != '\t'; cp++)
180 shellnamelen++; 173 shellnamelen++;
181 if (*cp == '\0') 174 if (*cp == '\0')
182 goto check_shell; 175 goto check_shell;
183 *cp++ = '\0'; 176 *cp++ = '\0';
184 177
185 /* skip spaces before any argument */ 178 /* skip spaces before any argument */
186 for ( /* cp = cp */ ; *cp == ' ' || *cp == '\t'; cp++) 179 for ( /* cp = cp */ ; *cp == ' ' || *cp == '\t'; cp++)
187 ; 180 ;
188 if (*cp == '\0') 181 if (*cp == '\0')
189 goto check_shell; 182 goto check_shell;
190 183
191 /* 184 /*
192 * collect the shell argument. everything after the shell name 185 * collect the shell argument. everything after the shell name
193 * is passed as ONE argument; that's the correct (historical) 186 * is passed as ONE argument; that's the correct (historical)
194 * behaviour. 187 * behaviour.
195 */ 188 */
196 shellarg = cp; 189 shellarg = cp;
197 for ( /* cp = cp */ ; *cp != '\0'; cp++) 190 for ( /* cp = cp */ ; *cp != '\0'; cp++)
198 shellarglen++; 191 shellarglen++;
199 *cp++ = '\0'; 192 *cp++ = '\0';
200 193
201check_shell: 194check_shell:
202#ifdef SETUIDSCRIPTS 195#ifdef SETUIDSCRIPTS
203 /* 196 /*
204 * MNT_NOSUID has already taken care of by check_exec, 197 * MNT_NOSUID has already taken care of by check_exec,
205 * so we don't need to worry about it now or later. We 198 * so we don't need to worry about it now or later. We
206 * will need to check PSL_TRACED later, however. 199 * will need to check PSL_TRACED later, however.
207 */ 200 */
208 script_sbits = epp->ep_vap->va_mode & (S_ISUID | S_ISGID); 201 script_sbits = epp->ep_vap->va_mode & (S_ISUID | S_ISGID);
209 if (script_sbits != 0) { 202 if (script_sbits != 0) {
210 script_uid = epp->ep_vap->va_uid; 203 script_uid = epp->ep_vap->va_uid;
211 script_gid = epp->ep_vap->va_gid; 204 script_gid = epp->ep_vap->va_gid;
212 } 205 }
213#endif 206#endif
214#ifdef FDSCRIPTS 207#ifdef FDSCRIPTS
215 /* 208 /*
216 * if the script isn't readable, or it's set-id, then we've 209 * if the script isn't readable, or it's set-id, then we've
217 * gotta supply a "/dev/fd/..." for the shell to read. 210 * gotta supply a "/dev/fd/..." for the shell to read.
218 * Note that stupid shells (csh) do the wrong thing, and 211 * Note that stupid shells (csh) do the wrong thing, and
219 * close all open fd's when the start. That kills this 212 * close all open fd's when the start. That kills this
220 * method of implementing "safe" set-id and x-only scripts. 213 * method of implementing "safe" set-id and x-only scripts.
221 */ 214 */
222 vn_lock(epp->ep_vp, LK_EXCLUSIVE | LK_RETRY); 215 vn_lock(epp->ep_vp, LK_EXCLUSIVE | LK_RETRY);
223 error = VOP_ACCESS(epp->ep_vp, VREAD, l->l_cred); 216 error = VOP_ACCESS(epp->ep_vp, VREAD, l->l_cred);
224 VOP_UNLOCK(epp->ep_vp); 217 VOP_UNLOCK(epp->ep_vp);
225 if (error == EACCES 218 if (error == EACCES
226#ifdef SETUIDSCRIPTS 219#ifdef SETUIDSCRIPTS
227 || script_sbits 220 || script_sbits
228#endif 221#endif
229 ) { 222 ) {
230 struct file *fp; 223 struct file *fp;
231 224
232#if defined(DIAGNOSTIC) && defined(FDSCRIPTS) 225#if defined(DIAGNOSTIC) && defined(FDSCRIPTS)
233 if (epp->ep_flags & EXEC_HASFD) 226 if (epp->ep_flags & EXEC_HASFD)
234 panic("exec_script_makecmds: epp already has a fd"); 227 panic("exec_script_makecmds: epp already has a fd");
235#endif 228#endif
236 229
237 if ((error = fd_allocfile(&fp, &epp->ep_fd)) != 0) { 230 if ((error = fd_allocfile(&fp, &epp->ep_fd)) != 0) {
238 scriptvp = NULL; 231 scriptvp = NULL;
239 shellargp = NULL; 232 shellargp = NULL;
240 goto fail; 233 goto fail;
241 } 234 }
242 epp->ep_flags |= EXEC_HASFD; 235 epp->ep_flags |= EXEC_HASFD;
243 fp->f_type = DTYPE_VNODE; 236 fp->f_type = DTYPE_VNODE;
244 fp->f_ops = &vnops; 237 fp->f_ops = &vnops;
245 fp->f_data = (void *) epp->ep_vp; 238 fp->f_data = (void *) epp->ep_vp;
246 fp->f_flag = FREAD; 239 fp->f_flag = FREAD;
247 fd_affix(curproc, fp, epp->ep_fd); 240 fd_affix(curproc, fp, epp->ep_fd);
248 } 241 }
249#endif 242#endif
250 243
251 /* set up the fake args list */ 244 /* set up the fake args list */
252 shellargp_len = 4 * sizeof(*shellargp); 245 shellargp_len = 4 * sizeof(*shellargp);
253 shellargp = kmem_alloc(shellargp_len, KM_SLEEP); 246 shellargp = kmem_alloc(shellargp_len, KM_SLEEP);
254 tmpsap = shellargp; 247 tmpsap = shellargp;
255 tmpsap->fa_len = shellnamelen + 1; 248 tmpsap->fa_len = shellnamelen + 1;
256 tmpsap->fa_arg = kmem_alloc(tmpsap->fa_len, KM_SLEEP); 249 tmpsap->fa_arg = kmem_alloc(tmpsap->fa_len, KM_SLEEP);
257 strlcpy(tmpsap->fa_arg, shellname, tmpsap->fa_len); 250 strlcpy(tmpsap->fa_arg, shellname, tmpsap->fa_len);
258 tmpsap++; 251 tmpsap++;
259 if (shellarg != NULL) { 252 if (shellarg != NULL) {
260 tmpsap->fa_len = shellarglen + 1; 253 tmpsap->fa_len = shellarglen + 1;
261 tmpsap->fa_arg = kmem_alloc(tmpsap->fa_len, KM_SLEEP); 254 tmpsap->fa_arg = kmem_alloc(tmpsap->fa_len, KM_SLEEP);
262 strlcpy(tmpsap->fa_arg, shellarg, tmpsap->fa_len); 255 strlcpy(tmpsap->fa_arg, shellarg, tmpsap->fa_len);
263 tmpsap++; 256 tmpsap++;
264 } 257 }
265 tmpsap->fa_len = MAXPATHLEN; 258 tmpsap->fa_len = MAXPATHLEN;
266 tmpsap->fa_arg = kmem_alloc(tmpsap->fa_len, KM_SLEEP); 259 tmpsap->fa_arg = kmem_alloc(tmpsap->fa_len, KM_SLEEP);
267#ifdef FDSCRIPTS 260#ifdef FDSCRIPTS
268 if ((epp->ep_flags & EXEC_HASFD) == 0) { 261 if ((epp->ep_flags & EXEC_HASFD) == 0) {
269#endif 262#endif
270 /* normally can't fail, but check for it if diagnostic */ 263 /* normally can't fail, but check for it if diagnostic */
271 error = copystr(epp->ep_kname, tmpsap->fa_arg, MAXPATHLEN, 264 error = copystr(epp->ep_kname, tmpsap->fa_arg, MAXPATHLEN,
272 (size_t *)0); 265 (size_t *)0);
273 tmpsap++; 266 tmpsap++;
274#ifdef DIAGNOSTIC 267#ifdef DIAGNOSTIC
275 if (error != 0) 268 if (error != 0)
276 panic("exec_script: copystr couldn't fail"); 269 panic("exec_script: copystr couldn't fail");
277#endif 270#endif
278#ifdef FDSCRIPTS 271#ifdef FDSCRIPTS
279 } else { 272 } else {
280 snprintf(tmpsap->fa_arg, MAXPATHLEN, "/dev/fd/%d", epp->ep_fd); 273 snprintf(tmpsap->fa_arg, MAXPATHLEN, "/dev/fd/%d", epp->ep_fd);
281 tmpsap++; 274 tmpsap++;
282 } 275 }
283#endif 276#endif
284 tmpsap->fa_arg = NULL; 277 tmpsap->fa_arg = NULL;
285 278
286 /* Save the old vnode so we can clean it up later. */ 279 /* Save the old vnode so we can clean it up later. */
287 scriptvp = epp->ep_vp; 280 scriptvp = epp->ep_vp;
288 epp->ep_vp = NULL; 281 epp->ep_vp = NULL;
289 282
290 /* Note that we're trying recursively. */ 283 /* Note that we're trying recursively. */
291 epp->ep_flags |= EXEC_INDIR; 284 epp->ep_flags |= EXEC_INDIR;
292 285
293 /* 286 /*
294 * mark the header we have as invalid; check_exec will read 287 * mark the header we have as invalid; check_exec will read
295 * the header from the new executable 288 * the header from the new executable
296 */ 289 */
297 epp->ep_hdrvalid = 0; 290 epp->ep_hdrvalid = 0;
298 291
299 /* try loading the interpreter */ 292 /* try loading the interpreter */
300 shell_pathbuf = pathbuf_create(shellname); 293 shell_pathbuf = pathbuf_create(shellname);
301 if (shell_pathbuf == NULL) { 294 if (shell_pathbuf == NULL) {
302 error = ENOMEM; 295 error = ENOMEM;
303 } else { 296 } else {
304 error = check_exec(l, epp, shell_pathbuf); 297 error = check_exec(l, epp, shell_pathbuf);
305 pathbuf_destroy(shell_pathbuf); 298 pathbuf_destroy(shell_pathbuf);
306 } 299 }
307 300
308 /* note that we've clobbered the header */ 301 /* note that we've clobbered the header */
309 epp->ep_flags |= EXEC_DESTR; 302 epp->ep_flags |= EXEC_DESTR;
310 303
311 if (error == 0) { 304 if (error == 0) {
312 /* 305 /*
313 * It succeeded. Unlock the script and 306 * It succeeded. Unlock the script and
314 * close it if we aren't using it any more. 307 * close it if we aren't using it any more.
315 * Also, set things up so that the fake args 308 * Also, set things up so that the fake args
316 * list will be used. 309 * list will be used.
317 */ 310 */
318 if ((epp->ep_flags & EXEC_HASFD) == 0) { 311 if ((epp->ep_flags & EXEC_HASFD) == 0) {
319 vn_lock(scriptvp, LK_EXCLUSIVE | LK_RETRY); 312 vn_lock(scriptvp, LK_EXCLUSIVE | LK_RETRY);
320 VOP_CLOSE(scriptvp, FREAD, l->l_cred); 313 VOP_CLOSE(scriptvp, FREAD, l->l_cred);
321 vput(scriptvp); 314 vput(scriptvp);
322 } 315 }
323 316
324 epp->ep_flags |= (EXEC_HASARGL | EXEC_SKIPARG); 317 epp->ep_flags |= (EXEC_HASARGL | EXEC_SKIPARG);
325 epp->ep_fa = shellargp; 318 epp->ep_fa = shellargp;
326 epp->ep_fa_len = shellargp_len; 319 epp->ep_fa_len = shellargp_len;
327#ifdef SETUIDSCRIPTS 320#ifdef SETUIDSCRIPTS
328 /* 321 /*
329 * set thing up so that set-id scripts will be 322 * set thing up so that set-id scripts will be
330 * handled appropriately. PSL_TRACED will be 323 * handled appropriately. PSL_TRACED will be
331 * checked later when the shell is actually 324 * checked later when the shell is actually
332 * exec'd. 325 * exec'd.
333 */ 326 */
334 epp->ep_vap->va_mode |= script_sbits; 327 epp->ep_vap->va_mode |= script_sbits;
335 if (script_sbits & S_ISUID) 328 if (script_sbits & S_ISUID)
336 epp->ep_vap->va_uid = script_uid; 329 epp->ep_vap->va_uid = script_uid;
337 if (script_sbits & S_ISGID) 330 if (script_sbits & S_ISGID)
338 epp->ep_vap->va_gid = script_gid; 331 epp->ep_vap->va_gid = script_gid;
339#endif 332#endif
340 return (0); 333 return (0);
341 } 334 }
342 335
343#ifdef FDSCRIPTS 336#ifdef FDSCRIPTS
344fail: 337fail:
345#endif 338#endif
346 339
347 /* kill the opened file descriptor, else close the file */ 340 /* kill the opened file descriptor, else close the file */
348 if (epp->ep_flags & EXEC_HASFD) { 341 if (epp->ep_flags & EXEC_HASFD) {
349 epp->ep_flags &= ~EXEC_HASFD; 342 epp->ep_flags &= ~EXEC_HASFD;
350 fd_close(epp->ep_fd); 343 fd_close(epp->ep_fd);
351 } else if (scriptvp) { 344 } else if (scriptvp) {
352 vn_lock(scriptvp, LK_EXCLUSIVE | LK_RETRY); 345 vn_lock(scriptvp, LK_EXCLUSIVE | LK_RETRY);
353 VOP_CLOSE(scriptvp, FREAD, l->l_cred); 346 VOP_CLOSE(scriptvp, FREAD, l->l_cred);
354 vput(scriptvp); 347 vput(scriptvp);
355 } 348 }
356 349
357 /* free the fake arg list, because we're not returning it */ 350 /* free the fake arg list, because we're not returning it */
358 if ((tmpsap = shellargp) != NULL) { 351 if ((tmpsap = shellargp) != NULL) {
359 while (tmpsap->fa_arg != NULL) { 352 while (tmpsap->fa_arg != NULL) {
360 kmem_free(tmpsap->fa_arg, tmpsap->fa_len); 353 kmem_free(tmpsap->fa_arg, tmpsap->fa_len);
361 tmpsap++; 354 tmpsap++;
362 } 355 }
363 kmem_free(shellargp, shellargp_len); 356 kmem_free(shellargp, shellargp_len);
364 } 357 }
365 358
366 /* 359 /*
367 * free any vmspace-creation commands, 360 * free any vmspace-creation commands,
368 * and release their references 361 * and release their references
369 */ 362 */
370 kill_vmcmds(&epp->ep_vmcmds); 363 kill_vmcmds(&epp->ep_vmcmds);
371 364
372 return error; 365 return error;
373} 366}