xref: /netbsd-src/share/man/man7/script.7 (revision 5e015e5e29314963f594bd9787e9b818f2f2c494)
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