|
|
Subscribe / Log in / New account

Safename: restricting "dangerous" file names

Safename: restricting "dangerous" file names

Posted May 17, 2016 18:47 UTC (Tue) by flussence (guest, #85566)
In reply to: Safename: restricting "dangerous" file names by farnz
Parent article: Safename: restricting "dangerous" file names

> there's no way for rm to know how to disambiguate things that are both options and filenames

You demonstrated this isn't the case only half a sentence later...


to post comments

Safename: restricting "dangerous" file names

Posted May 17, 2016 19:12 UTC (Tue) by farnz (subscriber, #17727) [Link] (15 responses)

I didn't. -fr is both a legitimate filename and an option to rm. The user can disambiguate them for rm by using a ./ prefix to say definitely a filename, but there is no equivalent for options, and the prefix is not required (nor is it put in there by shell expansions).

Thus the user can choose to be unambiguous, but if they are ambiguous, rm can't tell what they really meant - did I get -fr into argv[1] via glob expansion or tab completion (probably a filename) or by typing a literal -fr (probably an option).

Safename: restricting "dangerous" file names

Posted May 17, 2016 20:44 UTC (Tue) by hummassa (subscriber, #307) [Link] (14 responses)

You inadvertently came up with a nice and neat (IMHO) solution.

Just adjust your shell so that * and .* globs expand to ./* and ./.*, respectively

Safename: restricting "dangerous" file names

Posted May 17, 2016 20:51 UTC (Tue) by dlang (guest, #313) [Link]

just make sure you don't change foo* to foo./* in the process.

Safename: restricting "dangerous" file names

Posted May 18, 2016 9:59 UTC (Wed) by farnz (subscriber, #17727) [Link] (10 responses)

That's not enough; you need anything that the shell creates as a "filename" to expand to ./result; otherwise rm -* (typo) is also ambiguous. Plus, you need to do this before the current behaviour gets set in historic tradition, so that people don't write scripts containing things like rm -{f,r,v} and expect it to work.

Safename: restricting "dangerous" file names

Posted May 18, 2016 10:39 UTC (Wed) by itvirta (guest, #49997) [Link] (9 responses)

> ...scripts containing things like rm -{f,r,v} and expect it to work.

Uh, that's hideous. Luckily rm -frv usually works, and even rm -f -r -v is probably easier to write than that.
(Exactly the same amount of characters too.) So hopefully there's no need for that.

Safename: restricting "dangerous" file names

Posted May 18, 2016 10:48 UTC (Wed) by farnz (subscriber, #17727) [Link] (8 responses)

Unfortunately, because this has historically worked, it's now expected behaviour; I've worked with people who consider it the "definitive" style for options, and who prefer to do things like rm --{force,recursive,verbose} because they think that's clearer than rm --force --recursive --verbose. If that's deep in a script, my modified shell is going to break.

Hence coming back to my original point; had early UNIX authors foreseen this gotcha, they could have required relative paths to begin ./, and thus avoided all this pain down the line, because rm would never have been passed a filename without the ./. Now, though, it's too late - too much legacy to fix.

Safename: restricting "dangerous" file names

Posted May 18, 2016 13:05 UTC (Wed) by tao (subscriber, #17563) [Link]

Command line options is something that has always been broken, and is unlikely to ever unbreak.

tar, ar, ps, etc. don't even prefix their options with a dash (though you can).
Some commands require -- for long options, others don't.
Some commands enforce (or at least warn about) the ordering of options (find, for instance), others don't.

Simple fix: Only add ./ if bash know is it a file

Posted May 19, 2016 9:57 UTC (Thu) by gmatht (guest, #58961) [Link] (6 responses)

It it seems that there are only two cases
1) Bash knows that the glob is the file, because it had to scan the file system
2) Bash didn't have to scan the file system, so it safe to omit the './'

There are other ways adding ./ could break existing scripts though. For example, the following would no longer give you a list of naughty users:

cd /home; find * -name naughty.jpg | sed s,/.*,,g | sort -u

I guess "bash -n" could warn about unsafe use of "*", warn interactive users, and we could scan all packages for unsafe use of *.

Simple fix: Only add ./ if bash know is it a file

Posted May 19, 2016 9:59 UTC (Thu) by farnz (subscriber, #17727) [Link] (5 responses)

You missed case 3 - Bash did not have to scan the file system, but the user's intent was to match a file. For example rm log-{user,system}.txt. There's no way for Bash to detect that sanely without adding in a file system scan - but then the file system scan can cause bash to do the wrong thing for someone who does rm --{force,recursive}.

Simple fix: Only add ./ if bash know is it a file

Posted May 19, 2016 11:18 UTC (Thu) by anselm (subscriber, #2796) [Link] (2 responses)

Of course brace expansion, by definition, has nothing to do with existing files. There are lots of legimitate cases for brace expansion where the expansion results are file names that a file system scan won't uncover, because they don't exist. Consider

$ mkdir -p quarterly-results/201{5,6,7}q{1,2,3,4}

Doing a file system scan here to “validate” the expansion results would be completely pointless if not counterproductive.

Simple fix: Only add ./ if bash know is it a file

Posted May 19, 2016 11:31 UTC (Thu) by farnz (subscriber, #17727) [Link]

Indeed; hence me saying that this isn't actually fixable now. The chance to insist that paths, other strings, and options were distinct entities (with a - hint as first character of an option, and a . hint as the first character of a path, thus not needing a binary protocol to provide the hints) has long since gone away, especially since there are now programs like ps which use the presence or absence of the - to choose between different option parsers.

Simple fix: Only add ./ if bash know is it a file

Posted May 19, 2016 12:55 UTC (Thu) by tao (subscriber, #17563) [Link]

As an additional bonus this will yield different results depending on whether you run it on a basic POSIX-compliant shell or using bash.

touch a b
dash$ ls {a,b}
ls: cannot access '{a,b}': No such file or directory
bash$ ls {a,b}
a b

Case 3=2b

Posted May 20, 2016 4:22 UTC (Fri) by gmatht (guest, #58961) [Link] (1 responses)

Bash doesn't care whether log-user.txt is a file or an option. That is the application's job to decide. Scanning the file system wouldn't even help, for example: `tar x x`.

We don't know that log-{user,system}.txt is an option. We do know that log-{user,system}.txt is a fixed expansion, that doesn't directly depend on any untrusted filenames. So either way we can pass it directly to the application and it handle this ambiguity without worrying too much about the existence of files with malicious names tricking the application.

Case 3=2b

Posted May 20, 2016 8:15 UTC (Fri) by farnz (subscriber, #17727) [Link]

Exactly; if I meant it to be a filename, bash can't tell the application anything that hints that that was my intent. Equally, if I meant it to be an option, bash can't tell the application anything that hints that that was my intent.

Thus, this is currently an insoluble problem, without going back in time and changing the idioms for filenames and options such that filenames *always* began . or / (which then makes log-{user.system}.txt clearly not a filename, as it starts "l"), and options always began -; then, you reserve all other characters for parameters that are neither filenames nor options (e.g. PIDs and IP addresses). This is about 40 years too late now (I wasn't even born when the decisions were being made), so it's an insoluble problem because any shell trying to enforce this needs to cope with the legacy that's already out there.

Safename: restricting "dangerous" file names

Posted May 25, 2016 17:19 UTC (Wed) by Wol (subscriber, #4433) [Link] (1 responses)

> Just adjust your shell so that * and .* globs expand to ./* and ./.*, respectively

And then you do what we did, and blow up your system (well, we didn't exactly, but our backup system went mad...)

We installed a system ported across from Pr1mos. It used * everywhere as part of a filename ...

(* at the start of a name was sort of the equivalent of .exe in Windows. I'm not even sure it was stored in the directory tree on Pr1mos, but because they couldn't do whatever they did on Pr1mos, they put it in the directory tree on nix ...)

Cheers,
Wol

Safename: restricting "dangerous" file names

Posted May 25, 2016 20:55 UTC (Wed) by tao (subscriber, #17563) [Link]

Honestly, that kind of sounds like you did a bad port. The purpose of a port isn't to copy all stupid things from the source platform, but to adapt it to run well on the target system...

In the same manner I wouldn't limit filenames to 8.3 when porting from DOS to Linux, or allow backslash in filenames when porting the other way around...


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds