tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Possible "new" redirect style for /bin/sh (needs a name)



On Sat, Apr 10, 2021 at 08:38:58AM +0200, tlaronde%polynum.com@localhost wrote:
> Hello Robert,
> 
> On Sat, Apr 10, 2021 at 08:34:51AM +0700, Robert Elz wrote:
> > Sometime, in the now moderately distant past, I recall a notable
> > NetBSD developer say that the one useful thing missing from our /bin/sh
> > that is present in bash & ksh (and zsh) is {var}>whatever type redirects.
> > 
> > I have been hesitant about implementing this as I could not think
> > of a way (in our shell) to do it safely.
> > 
> > For anyone unaware, this kind of redirect does the redirect, picks
> > a "random" fd, ("random" here just means unknown to the script writer, no
> > mathematical randomness properties implied, or implemented) and assigns
> > its value to the variable named in the braces.   It is particularly useful
> > in functions, where a temporary fd is needed, but where it is unknown
> > which fds the application might be using (so the function cannot simply
> > safely pick fd=7 (or some other number) and hope).
> > 
> > Our problem is what "random" fd to assign?    Traditionally, shells
> > have simply assigned anything (currently unused) >= 10, and with ksh
> > that works fine, as users are only allowed to use (in redirects) fds
> > between 0 and 9 (incl) - that is, a single digit.   We don't have that
> > limitation, so I have always been worried about how to avoid
> > 
> > 	exec {var}>/some/hidden/file	; # sh assigns var=10 and fd 10 is open
> > 	# some arbitrary amount of intervening code here
> > 	exec 10>/other/public/file
> > 
> > 	echo secret text > ${var}
> > 
> > I could never see a way to stop that from happening.  Other shell internal
> > use fd's the shell can simply renumber when the user attempts to use the
> > same fd for the script's use (and we do that) - but that's not possible here
> > as we cannot tell what the user might have done with the contents of var
> > 
> > Eg:
> > 	exec {var}>/some/hidden/file
> > 	echo $var >/some/hidden/fd-number
> > 
> > and then later
> > 
> > 	echo whatever > "$(cat /some/hidden/fd-number)"
> > 
> > This kind of thing might seem particularly perverse, but it is perfectly
> > legal, and should work, and be safe.
> > 
> > I am still unable to think of a way to make this safe ... bash is currently
> > the only shell that has this problem, and there it is simply ignored.
> > It hasn't caused any reported problems, but that may be because most
> > shells still don't allow explicit use of an fd >= 10, so most scripts
> > simply don't attempt to do that.
> 
> Wouldn't be possible to flag "var" as being a "fd_var" (or whatever) and
> disallow a direct or indirect redirection to a fd that is superior or
> equal to some upper limit (see below) that is the minimum value
> of the range reserved for this kind of redirection, unless it is given
> as "$var"?
> 
> > 
> > Relying on that kind of "works much of the time" has never been good
> > enough for me.
> > 
> > While I still cannot think of a way to automatically handle this, I
> > do have a way to allow the script to tell the shell the biggest fd
> > it will ever use, after which the shell simply always assigns fds
> > bigger than that when using this new kind of redirect.   If the script
> > never explicitly uses fds >= 10, then it need do nothing (this is the
> > normal case), otherwise it should make some explicit reference to the
> > fd in code that is seen by the parser (it doesn't need to actually be
> > executed) before the {var}> type redirect is first executed.
> > 
> 
> Why not simply use fd the same way as memory is used, i.e. starting by both
> ends, to have variable stack and heap concurrently using the mem. 
> 
> Starting from 0 and increasing will be
> the range to be used directly by the script; starting from the end and
> decreasing will be the range for {var}>/some/file. The variable lower bound of
> the latter will be the limit to test against in the above security
> concern you have mentioned.

And to address the questions this could introduce, one could stipulate:

1) A var such as: exec {var}>/some/file is called  a "named fd" since it
shall be referred to by the variable and not by it's implementation
defined value;

2) A "named fd" var once set is neither writable nor directly
readable by the script; it is read-only except it is only "readable"
by the implementation;

3) Redirections are only allowed such as ">$var" via the name and not 
directly by the value (since "echo $var" gives "\n"), the following 
construction being the only one allowed for "variables" named fds:

if some_condition; then
	this_fd=var1
else
	this_fd=var2
fi

echo "something" > eval \$$this_fd

4) The current lower limit of named fds allocated can be retrieved by
the variable NAMEDFD_WATERMARK (or whatever). New named fds are only
allocated if there is room between the current upper limit of users
allocated fds and the NAMEDFD_WATERMARK. The named fds range grows
downward. The implementation only guarantees that fds strictly less than
NAMEDFD_WATEMARK are at the user disposition (at the moment) but doesn't
necessarily give the last value attributed to a named fd.

Hoping this makes some sense.

Best,
-- 
        Thierry Laronde <tlaronde +AT+ polynum +dot+ com>
                     http://www.kergis.com/
                    http://kertex.kergis.com/
                       http://www.sbfa.fr/
Key fingerprint = 0FF7 E906 FBAF FE95 FD89  250D 52B1 AE95 6006 F40C


Home | Main Index | Thread Index | Old Index