1.\" $NetBSD: script.7,v 1.6 2010/03/22 18:58:32 joerg Exp $ 2.\" 3.\" Copyright (c) 2005 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This document was originally contributed to The NetBSD Foundation 7.\" by Perry E. Metzger of Metzger, Dowdeswell & Co. LLC. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" POSSIBILITY OF SUCH DAMAGE. 29.\" 30.Dd May 6, 2005 31.Dt SCRIPT 7 32.Os 33.Sh NAME 34.Nm script 35.Nd interpreter script execution 36.Sh DESCRIPTION 37The system is capable of treating a text file containing commands 38intended for an interpreter, such as 39.Xr sh 1 40or 41.Xr awk 1 , 42as an executable program. 43.Pp 44An 45.Dq interpreter script 46is a file which has been set executable (see 47.Xr chmod 2 ) 48and which has a first line of the form: 49.Pp 50.D1 Li #! Ar pathname Op Ar argument 51.Pp 52The 53.Dq #! 54must appear as the first two characters of the file. 55A space between the 56.Dq #! 57and 58.Ar pathname 59is optional. 60At most one 61.Ar argument 62may follow 63.Ar pathname , 64and the length of the entire line is limited (see below). 65.Pp 66If such a file is executed (such as via the 67.Xr execve 2 68system call), the interpreter specified by the 69.Ar pathname 70is executed by the system. 71(The 72.Ar pathname 73is executed without regard to the 74.Ev PATH 75variable, so in general 76.Ar pathname 77should be an absolute path.) 78.Pp 79The arguments passed to the interpreter will be as follows. 80.Va argv[0] 81will be the path to the interpreter itself, as specified on the first 82line of the script. 83If there is an 84.Ar argument 85following 86.Ar pathname 87on the first line of the script, it will be passed as 88.Va argv[1] . 89The subsequent elements of 90.Va argv 91will be the path to the interpreter script file itself (i.e. the 92original 93.Va argv[0] ) 94followed by any further arguments passed when 95.Xr execve 2 96was invoked to execute the script file. 97.Pp 98By convention, it is expected that an interpreter will open the script 99file passed as an argument and process the commands within it. 100Typical interpreters treat 101.Sq # 102as a comment character, and thus will ignore the initial line of the script 103because it begins 104.Dq #! , 105but there is no requirement for this per se. 106.Pp 107On 108.Nx , 109the length of the 110.Dq #! 111line, excluding the 112.Dq #! 113itself, is limited to 114.Dv PATH_MAX 115(as defined in 116.In limits.h ) . 117Other operating systems impose much smaller limits on the length of 118the 119.Dq #! 120line (see below). 121.Pp 122Note that the interpreter may not itself be an interpreter script. 123If 124.Ar pathname 125does not point to an executable binary, execution of the interpreter 126script will fail. 127.Ss Trampolines and Portable Scripts 128Different operating systems often have interpreters located in 129different locations, and the kernel executes the passed interpreter 130without regard to the setting of environment variables such as 131.Ev PATH . 132This makes it somewhat challenging to set the 133.Dq #! 134line of a script so that it will run identically on different systems. 135.Pp 136Since the 137.Xr env 1 138utility executes a command passed to it on its command line, it is 139often used as a 140.Dq trampoline 141to render scripts portable. 142If the leading line of a script reads 143.Dl #! /usr/bin/env interp 144then the 145.Xr env 1 146command will execute the 147.Dq interp 148command it finds in its 149.Ev PATH , 150passing on to it all subsequent arguments with which it itself was called. 151Since 152.Pa /usr/bin/env 153is found on almost all 154.Tn POSIX 155style systems, this trick is frequently exploited by authors who need 156a script to execute without change on multiple systems. 157.Ss Historical Note: Scripts without Dq #! 158Shell scripts predate the invention of the 159.Dq #! 160convention, which is implemented in the kernel. 161In the days of 162.At v7 , 163there was only one interpreter used on the system, 164.Pa /bin/sh , 165and the shell treated any file that failed to execute with an 166.Er ENOEXEC 167error 168(see 169.Xr intro 2 ) 170as a shell script. 171.Pp 172Most shells (such as 173.Xr sh 1 ) 174and certain other facilities (including 175.Xr execlp 3 176and 177.Xr execvp 3 178but not other types of 179.Xr exec 3 180calls) still pass 181interpreter scripts that do not include the 182.Dq #! 183(and thus fail to execute with 184.Er ENOEXEC ) 185to 186.Pa /bin/sh . 187.Pp 188As this behavior is implemented outside the kernel, there is no 189mechanism that forces it to be respected by all programs that execute 190other programs. 191It is thus not completely reliable. 192It is therefore important to always include 193.Dl #!/bin/sh 194in front of Bourne shell scripts, and to treat the traditional 195behavior as obsolete. 196.Sh EXAMPLES 197Suppose that an executable binary exists in 198.Pa /bin/interp 199and that the file 200.Pa /tmp/script 201contains: 202.Bd -literal -offset indent 203#!/bin/interp -arg 204 205[...] 206.Ed 207.Pp 208and that 209.Pa /tmp/script 210is set mode 755. 211.Pp 212Executing 213.Pp 214.Dl $ /tmp/script one two three 215.Pp 216at the shell will result in 217.Pa /bin/interp 218being executed, receiving the following arguments in 219.Va argv 220(numbered from 0): 221.Pp 222.Bd -ragged -offset indent 223.Qq /bin/interp , 224.Qq "-arg" , 225.Qq /tmp/script , 226.Qq one , 227.Qq two , 228.Qq three 229.Ed 230.Ss Portability Note: Multiple arguments 231The behavior of multiple arguments on the 232.Dq #! 233line is highly non-portable between different systems. 234In general, only one argument can be assumed to work consistently. 235.Pp 236Consider the following variation on the previous example. 237Suppose that an executable binary exists in 238.Pa /bin/interp 239and that the file 240.Pa /tmp/script 241contains: 242.Bd -literal -offset indent 243#!/bin/interp -x -y 244 245[...] 246.Ed 247.Pp 248and that 249.Pa /tmp/script 250is set mode 755. 251.Pp 252Executing 253.Pp 254.Dl $ /tmp/script one two three 255.Pp 256at the shell will result in 257.Pa /bin/interp 258being executed, receiving the following arguments in 259.Va argv 260(numbered from 0): 261.Pp 262.Bd -ragged -offset indent 263.Qq /bin/interp , 264.Qq "-x -y" , 265.Qq /tmp/script , 266.Qq one , 267.Qq two , 268.Qq three 269.Ed 270.Pp 271Note that 272.Qq "-x -y" 273will be passed on 274.Nx 275as a single argument. 276.Pp 277Although most 278.Tn POSIX 279style operating systems will pass only one 280.Ar argument , 281the behavior when multiple arguments are included is not 282consistent between platforms. 283Some, such as current releases of 284.Nx , 285will concatenate multiple arguments into a single argument (as above), 286some will truncate them, and at least one will pass them as multiple 287arguments. 288.Pp 289The 290.Nx 291behavior is common but not universal. 292Sun's 293.Tn Solaris 294would present the above argument as 295.Qq -x , 296dropping the 297.Qq " -y" 298entirely. 299Perhaps uniquely, recent versions of Apple's 300.Tn OS X 301will actually pass multiple arguments properly, i.e.: 302.Bd -ragged -offset indent 303.Qq /bin/interp , 304.Qq -x , 305.Qq -y , 306.Qq /tmp/script , 307.Qq one , 308.Qq two , 309.Qq three 310.Ed 311.Pp 312The behavior of the system in the face of multiple arguments is thus 313not currently standardized, should not be relied on, and may be 314changed in future releases. 315In general, pass at most one argument, and do not rely on multiple 316arguments being concatenated. 317.Sh SEE ALSO 318.Xr awk 1 , 319.Xr csh 1 , 320.Xr ksh 1 , 321.Xr sh 1 , 322.Xr chmod 2 , 323.Xr execve 2 , 324.Xr intro 2 , 325.Xr execlp 3 , 326.Xr execvp 3 , 327.Xr fd 4 , 328.Xr options 4 , 329.Xr setuid 7 330.Sh STANDARDS 331The behavior of interpreter scripts is obliquely referred to, but 332never actually described in, 333.St -p1003.1-2004 . 334.Pp 335The behavior is partially (but not completely) described in the 336.St -svid4 . 337.Pp 338Although it has never been formally standardized, the behavior 339described is largely portable across 340.Tn POSIX 341style systems, with two significant exceptions: the maximum length of the 342.Dq #! 343line, and the behavior if multiple arguments are passed. 344Please be aware that some operating systems limit the line to 32 345or 64 characters, and that (as described above) the behavior in the 346face of multiple arguments is not consistent across systems. 347.Sh HISTORY 348The behavior of the kernel when encountering scripts that start in 349.Dq #! 350was not present in 351.At v7 . 352A Usenet posting to net.unix by Guy Harris on October 16, 1984 claims 353that the idea for the 354.Dq #! 355behavior was first proposed by Dennis Ritchie but that the first 356implementation was on 357.Bx . 358.Pp 359Historical manuals (specifically the exec man page) indicate that the 360behavior was present in 361.Bx 4 362at least as early as April, 1981. 363Information on precisely when it was first implemented, and in which 364version of 365.Ux , 366is solicited. 367.Sh SECURITY CONSIDERATIONS 368Numerous security problems are associated with setuid interpreter 369scripts. 370.Pp 371In addition to the fact that many interpreters (and scripts) are 372simply not designed to be robust in a setuid context, a race condition 373exists between the moment that the kernel examines the interpreter 374script file and the moment that the newly invoked interpreter opens 375the file itself. 376.Pp 377Because of these security issues, 378.Nx 379does not allow setuid interpreter scripts by default. 380In order to turn on setuid interpreter scripts, 381.D1 Cd options SETUIDSCRIPTS 382must be set in the configuration of the running kernel. 383Setting this option implies the 384.Cd FDSCRIPTS 385option, which causes the kernel to open the script file on behalf of 386the interpreter and pass it in 387.Va argv 388as 389.Pa /dev/fd/[fdnum] . 390(See 391.Xr fd 4 392for an explanation of the 393.Pa /dev/fd/[fdnum] 394devices.) 395This design avoids the race condition, at the cost of denying the 396interpreter the actual name of the script file. 397See 398.Xr options 4 399for more information. 400.Pp 401However, the 402.Cd FDSCRIPTS 403mechanism is not a cure-all for security issues in setuid interpreters 404and scripts. 405Subtle techniques can be used to subvert even seemingly well written scripts. 406Scripts executed by Bourne type shells can be subverted in numerous 407ways, such as by setting the 408.Ev IFS 409variable before executing the script. 410Other interpreters possess their own vulnerabilities. 411Turning on 412.Cd SETUIDSCRIPTS 413is therefore very dangerous, and should not be done lightly if at all. 414