Globbing
Simon 'corecode' Schubert
corecode at fs.ei.tum.de
Fri Feb 15 03:30:22 PST 2008
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 / \
More information about the Kernel
mailing list