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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2012 Milan Jurik. All rights reserved. 25 * Copyright 2019 Joyent, Inc. 26 */ 27 28 /* Copyright (c) 1988 AT&T */ 29 /* All Rights Reserved */ 30 31 32 /* from S5R4 1.6 */ 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/sysmacros.h> 37 #include <sys/signal.h> 38 #include <sys/cred.h> 39 #include <sys/user.h> 40 #include <sys/errno.h> 41 #include <sys/vnode.h> 42 #include <sys/proc.h> 43 #include <sys/cmn_err.h> 44 #include <sys/debug.h> 45 #include <sys/pathname.h> 46 #include <sys/disp.h> 47 #include <sys/exec.h> 48 #include <sys/kmem.h> 49 #include <sys/note.h> 50 #include <sys/sdt.h> 51 52 /* 53 * This is the loadable module wrapper. 54 */ 55 #include <sys/modctl.h> 56 57 extern int intpexec(struct vnode *, struct execa *, struct uarg *, 58 struct intpdata *, int, size_t *, int, caddr_t, struct cred *, int); 59 60 static struct execsw esw = { 61 intpmagicstr, 62 0, 63 2, 64 intpexec, 65 NULL 66 }; 67 68 /* 69 * Module linkage information for the kernel. 70 */ 71 extern struct mod_ops mod_execops; 72 73 static struct modlexec modlexec = { 74 &mod_execops, "exec mod for interp", &esw 75 }; 76 77 static struct modlinkage modlinkage = { 78 MODREV_1, (void *)&modlexec, NULL 79 }; 80 81 int 82 _init() 83 { 84 return (mod_install(&modlinkage)); 85 } 86 87 int 88 _fini() 89 { 90 return (mod_remove(&modlinkage)); 91 } 92 93 int 94 _info(struct modinfo *modinfop) 95 { 96 return (mod_info(&modlinkage, modinfop)); 97 } 98 99 100 /* 101 * Crack open a '#!' line. 102 */ 103 static int 104 getintphead(struct vnode *vp, struct intpdata *idatap) 105 { 106 int error; 107 char *cp, *linep = idatap->intp; 108 ssize_t resid; 109 110 /* 111 * Read the entire line and confirm that it starts with '#!'. 112 */ 113 if (error = vn_rdwr(UIO_READ, vp, linep, INTPSZ, (offset_t)0, 114 UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid)) 115 return (error); 116 if (resid > INTPSZ-2 || linep[0] != '#' || linep[1] != '!') 117 return (ENOEXEC); 118 /* 119 * Blank all white space and find the newline. 120 */ 121 for (cp = &linep[2]; cp < &linep[INTPSZ] && *cp != '\n'; cp++) 122 if (*cp == '\t') 123 *cp = ' '; 124 if (cp >= &linep[INTPSZ]) 125 return (ENOEXEC); 126 ASSERT(*cp == '\n'); 127 *cp = '\0'; 128 129 /* 130 * Locate the beginning and end of the interpreter name. 131 * In addition to the name, one additional argument may 132 * optionally be included here, to be prepended to the 133 * arguments provided on the command line. Thus, for 134 * example, you can say 135 * 136 * #! /usr/bin/awk -f 137 */ 138 for (cp = &linep[2]; *cp == ' '; cp++) 139 ; 140 if (*cp == '\0') 141 return (ENOEXEC); 142 idatap->intp_name[0] = cp; 143 while (*cp && *cp != ' ') 144 cp++; 145 if (*cp == '\0') { 146 idatap->intp_arg[0] = NULL; 147 } else { 148 *cp++ = '\0'; 149 while (*cp == ' ') 150 cp++; 151 if (*cp == '\0') 152 idatap->intp_arg[0] = NULL; 153 else { 154 idatap->intp_arg[0] = cp; 155 while (*cp && *cp != ' ') 156 cp++; 157 *cp = '\0'; 158 } 159 } 160 return (0); 161 } 162 163 /* 164 * We support nested interpreters up to a depth of INTP_MAXDEPTH (this value 165 * matches the depth on Linux). When a nested interpreter is in use, the 166 * previous name and argument must be passed along. We use the intpdata_t 167 * name and argument arrays for this. In the normal, non-nested case, only the 168 * first element in those arrays will be populated. 169 * 170 * For setid scripts the "script hole" is a security race condition between 171 * when we exec the interpreter and when the interpreter reads the script. We 172 * handle this below for the initial script, but we don't allow setid scripts 173 * when using nested interpreters. Because gexec only modifies the credentials 174 * for a setid script at level 0, then if we come back through for a nested 175 * interpreter we know that args->fname will be set (the first script is setid) 176 * and we can return an error. If an intermediate nested interpreter is setid 177 * then it will not be run with different credentials because of the gexec 178 * handling, so it is effectively no longer setid and we don't have to worry 179 * about the "script hole". 180 */ 181 int 182 intpexec( 183 struct vnode *vp, 184 struct execa *uap, 185 struct uarg *args, 186 struct intpdata *idatap, 187 int level, 188 size_t *execsz, 189 int setid, 190 caddr_t exec_file, 191 struct cred *cred, 192 int brand_action) 193 { 194 _NOTE(ARGUNUSED(brand_action)) 195 vnode_t *nvp; 196 int error = 0; 197 struct intpdata idata; 198 struct pathname intppn; 199 struct pathname resolvepn; 200 char *opath; 201 char devfd[19]; /* 32-bit int fits in 10 digits + 8 for "/dev/fd/" */ 202 int fd = -1; 203 204 if (level >= INTP_MAXDEPTH) { /* Can't recurse past maxdepth */ 205 error = ELOOP; 206 goto bad; 207 } 208 209 if (level == 0) 210 ASSERT(idatap == (struct intpdata *)NULL); 211 212 bzero(&idata, sizeof (intpdata_t)); 213 214 /* 215 * Allocate a buffer to read in the interpreter pathname. 216 */ 217 idata.intp = kmem_alloc(INTPSZ, KM_SLEEP); 218 if (error = getintphead(vp, &idata)) 219 goto fail; 220 221 /* 222 * Look the new vnode up. 223 */ 224 if (error = pn_get(idata.intp_name[0], UIO_SYSSPACE, &intppn)) 225 goto fail; 226 pn_alloc(&resolvepn); 227 if (error = lookuppn(&intppn, &resolvepn, FOLLOW, NULLVPP, &nvp)) { 228 pn_free(&resolvepn); 229 pn_free(&intppn); 230 goto fail; 231 } 232 233 if (level > 0) { 234 /* 235 * We have a nested interpreter. The previous name(s) and 236 * argument(s) need to be passed along. We also keep track 237 * of how often this zone uses nested interpreters. 238 */ 239 int i; 240 241 atomic_inc_32(&curproc->p_zone->zone_nested_intp); 242 243 ASSERT(idatap != NULL); 244 /* since we're shifting up, loop stops one short */ 245 for (i = 0; i < (INTP_MAXDEPTH - 1); i++) { 246 idata.intp_name[i + 1] = idatap->intp_name[i]; 247 idata.intp_arg[i + 1] = idatap->intp_arg[i]; 248 } 249 250 DTRACE_PROBE3(nested__intp, int, level, void *, &idata, 251 void *, nvp); 252 } 253 254 opath = args->pathname; 255 args->pathname = resolvepn.pn_path; 256 /* don't free resolvepn until we are done with args */ 257 pn_free(&intppn); 258 259 /* 260 * Disallow setuid or additional privilege execution for nested 261 * interpreters. 262 */ 263 if (level > 0 && args->fname != NULL) { 264 error = ENOEXEC; 265 goto done; 266 } 267 268 /* 269 * When we're executing a set-uid script resulting in uids 270 * mismatching or when we execute with additional privileges, 271 * we close the "replace script between exec and open by shell" 272 * hole by passing the script as /dev/fd parameter. 273 */ 274 if ((setid & EXECSETID_PRIVS) != 0 || 275 (setid & (EXECSETID_UGIDS|EXECSETID_SETID)) == 276 (EXECSETID_UGIDS|EXECSETID_SETID)) { 277 (void) strcpy(devfd, "/dev/fd/"); 278 if (error = execopen(&vp, &fd)) 279 goto done; 280 numtos(fd, &devfd[8]); 281 args->fname = devfd; 282 } 283 284 error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred, 285 EBA_NONE); 286 287 if (!error) { 288 /* 289 * Close this executable as the interpreter 290 * will open and close it later on. 291 */ 292 (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, cred, NULL); 293 } 294 done: 295 VN_RELE(nvp); 296 args->pathname = opath; 297 pn_free(&resolvepn); 298 fail: 299 kmem_free(idata.intp, INTPSZ); 300 if (error && fd != -1) 301 (void) execclose(fd); 302 bad: 303 return (error); 304 } 305