d358fa780b
Shell syntax is too complicated to detect command substitution and unquoted operators reliably without implementing much of sh's parser. Therefore, have sh do this detection. While changing sh's support anyway, also read input from a pipe instead of arguments to avoid {ARG_MAX} limits and improve privacy, and output count and length using 16 instead of 8 digits. The basic concept is: execl("/bin/sh", "sh", "-c", "freebsd_wordexp ${1:+\"$1\"} -f "$2", "", flags & WRDE_NOCMD ? "-p" : "", <pipe with words>); The WRDE_BADCHAR error is still implemented in libc. POSIX requires us to fail strings containing unquoted braces with code WRDE_BADCHAR. Since this is normally not a syntax error in sh, there is still a need for checking code in libc, we_check(). The new we_check() is an optimistic check that all the characters <newline> | & ; < > ( ) { } are quoted. To avoid duplicating too much sh logic, such characters are permitted when quoting characters are seen, even if the quoting characters may themselves be quoted. This code reports all WRDE_BADCHAR errors; bad characters that get past it and are a syntax error in sh return WRDE_SYNTAX. Although many implementations of WRDE_NOCMD erroneously allow some command substitutions (and ours even documented this), there appears to be code that relies on its security (codesearch.debian.net shows quite a few uses). Passing untrusted data to wordexp() still exposes a denial of service possibility and a fairly large attack surface. Reviewed by: wblock (man page only) MFC after: 2 weeks Relnotes: yes Security: fixes command execution with wordexp(untrusted, WRDE_NOCMD)
211 lines
5.0 KiB
Groff
211 lines
5.0 KiB
Groff
.\"
|
|
.\" Copyright (c) 2002 Tim J. Robbins
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
.\" SUCH DAMAGE.
|
|
.\"
|
|
.\" $FreeBSD$
|
|
.\"
|
|
.Dd September 30, 2015
|
|
.Dt WORDEXP 3
|
|
.Os
|
|
.Sh NAME
|
|
.Nm wordexp
|
|
.Nd "perform shell-style word expansions"
|
|
.Sh LIBRARY
|
|
.Lb libc
|
|
.Sh SYNOPSIS
|
|
.In wordexp.h
|
|
.Ft int
|
|
.Fn wordexp "const char * restrict words" "wordexp_t * restrict we" "int flags"
|
|
.Ft void
|
|
.Fn wordfree "wordexp_t *we"
|
|
.Sh DESCRIPTION
|
|
The
|
|
.Fn wordexp
|
|
function performs shell-style word expansion on
|
|
.Fa words
|
|
and places the list of words into the
|
|
.Va we_wordv
|
|
member of
|
|
.Fa we ,
|
|
and the number of words into
|
|
.Va we_wordc .
|
|
.Pp
|
|
The
|
|
.Fa flags
|
|
argument is the bitwise inclusive OR of any of the following constants:
|
|
.Bl -tag -width ".Dv WRDE_SHOWERR"
|
|
.It Dv WRDE_APPEND
|
|
Append the words to those generated by a previous call to
|
|
.Fn wordexp .
|
|
.It Dv WRDE_DOOFFS
|
|
As many
|
|
.Dv NULL
|
|
pointers as are specified by the
|
|
.Va we_offs
|
|
member of
|
|
.Fa we
|
|
are added to the front of
|
|
.Va we_wordv .
|
|
.It Dv WRDE_NOCMD
|
|
Disallow command substitution in
|
|
.Fa words .
|
|
See the note in
|
|
.Sx BUGS
|
|
before using this.
|
|
.It Dv WRDE_REUSE
|
|
The
|
|
.Fa we
|
|
argument was passed to a previous successful call to
|
|
.Fn wordexp
|
|
but has not been passed to
|
|
.Fn wordfree .
|
|
The implementation may reuse the space allocated to it.
|
|
.It Dv WRDE_SHOWERR
|
|
Do not redirect shell error messages to
|
|
.Pa /dev/null .
|
|
.It Dv WRDE_UNDEF
|
|
Report error on an attempt to expand an undefined shell variable.
|
|
.El
|
|
.Pp
|
|
The
|
|
.Vt wordexp_t
|
|
structure is defined in
|
|
.In wordexp.h
|
|
as:
|
|
.Bd -literal -offset indent
|
|
typedef struct {
|
|
size_t we_wordc; /* count of words matched */
|
|
char **we_wordv; /* pointer to list of words */
|
|
size_t we_offs; /* slots to reserve in we_wordv */
|
|
} wordexp_t;
|
|
.Ed
|
|
.Pp
|
|
The
|
|
.Fn wordfree
|
|
function frees the memory allocated by
|
|
.Fn wordexp .
|
|
.Sh IMPLEMENTATION NOTES
|
|
The
|
|
.Fn wordexp
|
|
function is implemented using the undocumented
|
|
.Ic freebsd_wordexp
|
|
shell built-in command.
|
|
.Sh RETURN VALUES
|
|
The
|
|
.Fn wordexp
|
|
function returns zero if successful, otherwise it returns one of the following
|
|
error codes:
|
|
.Bl -tag -width ".Dv WRDE_NOSPACE"
|
|
.It Dv WRDE_BADCHAR
|
|
The
|
|
.Fa words
|
|
argument contains one of the following unquoted characters:
|
|
.Aq newline ,
|
|
.Ql | ,
|
|
.Ql & ,
|
|
.Ql \&; ,
|
|
.Ql < ,
|
|
.Ql > ,
|
|
.Ql \&( ,
|
|
.Ql \&) ,
|
|
.Ql { ,
|
|
.Ql } .
|
|
.It Dv WRDE_BADVAL
|
|
An error after successful parsing,
|
|
such as an attempt to expand an undefined shell variable with
|
|
.Dv WRDE_UNDEF
|
|
set in
|
|
.Fa flags .
|
|
.It Dv WRDE_CMDSUB
|
|
An attempt was made to use command substitution and
|
|
.Dv WRDE_NOCMD
|
|
is set in
|
|
.Fa flags .
|
|
.It Dv WRDE_NOSPACE
|
|
Not enough memory to store the result or
|
|
an error during
|
|
.Xr fork 2 .
|
|
.It Dv WRDE_SYNTAX
|
|
Shell syntax error in
|
|
.Fa words .
|
|
.El
|
|
.Pp
|
|
The
|
|
.Fn wordfree
|
|
function returns no value.
|
|
.Sh ENVIRONMENT
|
|
.Bl -tag -width ".Ev IFS"
|
|
.It Ev IFS
|
|
Field separator.
|
|
.El
|
|
.Sh EXAMPLES
|
|
Invoke the editor on all
|
|
.Pa .c
|
|
files in the current directory
|
|
and
|
|
.Pa /etc/motd
|
|
(error checking omitted):
|
|
.Bd -literal -offset indent
|
|
wordexp_t we;
|
|
|
|
wordexp("${EDITOR:-vi} *.c /etc/motd", &we, 0);
|
|
execvp(we.we_wordv[0], we.we_wordv);
|
|
.Ed
|
|
.Sh DIAGNOSTICS
|
|
Diagnostic messages from the shell are written to the standard error output
|
|
if
|
|
.Dv WRDE_SHOWERR
|
|
is set in
|
|
.Fa flags .
|
|
.Sh SEE ALSO
|
|
.Xr sh 1 ,
|
|
.Xr fnmatch 3 ,
|
|
.Xr glob 3 ,
|
|
.Xr popen 3 ,
|
|
.Xr system 3
|
|
.Sh STANDARDS
|
|
The
|
|
.Fn wordexp
|
|
and
|
|
.Fn wordfree
|
|
functions conform to
|
|
.St -p1003.1-2001 .
|
|
.Sh BUGS
|
|
The current
|
|
.Fn wordexp
|
|
implementation does not recognize multibyte characters other than UTF-8, since
|
|
the shell (which it invokes to perform expansions) does not.
|
|
.Sh SECURITY CONSIDERATIONS
|
|
Pathname generation may create output that is exponentially larger than the
|
|
input size.
|
|
.Pp
|
|
Although this implementation detects command substitution reliably for
|
|
.Dv WRDE_NOCMD ,
|
|
the attack surface remains fairly large.
|
|
Also, some other implementations
|
|
(such as older versions of this one)
|
|
may execute command substitutions even if
|
|
.Dv WRDE_NOCMD
|
|
is set.
|