DragonFly kernel List (threaded) for 2008-02
DragonFly BSD
DragonFly kernel List (threaded) for 2008-02
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: Globbing


From: "Simon 'corecode' Schubert" <corecode@xxxxxxxxxxxx>
Date: Fri, 15 Feb 2008 12:24:06 +0100

Oliver Fromme wrote:
echo * | xargs rm

That's what I've been using in such cases for 15 years.
Works in every shell.  (Do not use it in world-writable
directories, though; it can be exploited.  But the same
is true for "rm *", too.)

I'll take the opportunity to educate the uneducated:


echo * | xargs rm, like find . -type f | xargs rm can be exploited, because xargs treats every whitespace as a separation character.

Now passing in (arbitrarily, due to public writable directory) white space separated strings can have bad side effects:

touch keep delete1 delete2
touch 'delete keep'	# evil communist spy
echo delete* | xargs rm

xargs will call rm with the parameters 'delete1', 'delete2', 'delete' and 'keep'. Voila, keep is gone. rm will complain about delete not existing, but will happily remove keep anyways.

You can work around this by using find . -print0 | xargs -0, which is non-standard, IIRC.

Considering this, my rm() shell function was insecure as well :/

Now you also see why arguments and input from files (or pipes) is inherently different. Arguments can contain arbitrary whitespace which won't get munged. When reading from a fd, every program has to do the splitting itself, which is usually done on either a) any whitespace or b) newlines. Now newline characters are valid in file names as well, so neither (a) nor (b) are a solution.

The only character not allowed in file names is ASCII NUL (binary 0). But then, most tools work on newlines as separation characters and not on NULs. Writing code which deals with NUL characters is even more complicated, as C strings are terminated by a NUL character, and you lose the ability to easily distinguish end-of-string and end-of-record.

As we can see, there *is* a problem, but not really in the argument space, but rather in the globbing / file name splitting/handling. If somebody has a clever idea on how to approach this, please tell me.

rm * works, because the shell does the globbing and properly puts the file names into arguments, which then are not subject to white space splitting anymore.

By the way, when dealing with file names in variables in shell, always quote:

for f in *; do
  mv "$f" "$f.2"
done

This is because shell does word splitting after variable expansion. There is a special construct ("$@") for passing all parameters, without whitepsace splitting:

exec foo -b -a -r "$@"

cheers
  simon

--
Serve - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /"\
Work - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \ /
Party Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \
Dude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \




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