Bug 413 - Unexpected change in quoting behaviour with -i flag
Unexpected change in quoting behaviour with -i flag
Status: ASSIGNED
Product: Sudo
Classification: Unclassified
Component: Sudo
1.7.0
PC Linux
: low high
Assigned To: Todd C. Miller
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2010-06-16 12:52 MDT by Ian
Modified: 2010-06-29 11:30 MDT (History)
1 user (show)

See Also:


Attachments
Patch to quote non alphanumerics when running a command via "sudo -s" or "sudo -i" (1.46 KB, patch)
2010-06-16 14:33 MDT, Todd C. Miller
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ian 2010-06-16 12:52:26 MDT
Seen: 

$ sudo ls -l "thing not here"
ls: cannot access thing not here: No such file or directory

$ sudo -i ls -l "thing not here"
ls: cannot access thing: No such file or directory
ls: cannot access not: No such file or directory
ls: cannot access here: No such file or directory


Expected:

Seen: 

$ sudo ls -l "thing not here"
ls: cannot access thing not here: No such file or directory

$ sudo -i ls -l "thing not here"
ls: cannot access thing not here: No such file or directory


I can't see anything that suggests '-i' would affect the use of arguments, just the environment in which the command runs.

[I would consider anything that could possibly run the wrong command in 'sudo' a high priority bug.]
Comment 1 Todd C. Miller 2010-06-16 13:09:55 MDT
The problem is that the shell removes the quotes when the command is executed so when sudo joins the exec arguments it effectively runs:

sh -c "ls -l thing not here"

If you do: sudo -i \"thing not here\"

you get the expected behavior.  I'll change the way the arguments are handled to quote ones with spaces which should resolve the issue.
Comment 2 Todd C. Miller 2010-06-16 14:33:28 MDT
Created attachment 276 [details]
Patch to quote non alphanumerics when running a command via "sudo -s" or "sudo -i"

I've attached a patch that fixes the problem.
Comment 3 Paolo Herms 2010-06-28 12:09:47 MDT
(In reply to comment #1)
> The problem is that the shell removes the quotes when the command is executed
> so when sudo joins the exec arguments it effectively runs:
> 
> sh -c "ls -l thing not here"
> 
> If you do: sudo -i \"thing not here\"
> 
> you get the expected behavior.  I'll change the way the arguments are handled
> to quote ones with spaces which should resolve the issue.

You better should let the shell do this job itself.
Instead of executing 
  sh -c "ls -l thing not here"
you just execute 
  sh -c 'ls $@' "thing not here"
This doesn't require any wild argument-string modification, the user provided arguments remain the same. The only thing you need to do is to append the string '$@' to the command to be executed as the second argument of sh and then use the elements in argv as following arguments.
Comment 4 Todd C. Miller 2010-06-28 12:20:05 MDT
That's not possible as the shell is not running at that point; there is nothing to expand "$@".
Comment 5 Paolo Herms 2010-06-28 12:27:58 MDT
(In reply to comment #4)
> That's not possible as the shell is not running at that point; there is nothing
> to expand "$@".

I'm sorry, I see this wasn't clear. The $@ must not be expanded, it must be passed to the shell within the command string. The shell will then expand it to the arguments that follow.
Just a detail though: when using the form 
  sh -c cmd args...
the arguments are assigned to the positional parameters starting from 0, so you
the user arguments need to start one further.
So this is what you need to execute:
  sh -c 'usercmd "$@"' usercmd userarg1 userarg2 ...
Comment 6 Paolo Herms 2010-06-28 12:31:41 MDT
Just try it out, type this into your terminal:
  sh -c 'ls "$@"' ls bla "bla bla"
Comment 7 Todd C. Miller 2010-06-28 13:34:26 MDT
Unfortunately, that is bourne-shell specific so it won't work for all shells.  One possibility would be to have a whitelist of "good" shells to use the "$@" trick for and then just quote non-alphanumerics for anything else.
Comment 8 Paolo Herms 2010-06-29 04:11:15 MDT
That's right so it also works in korn shell and all POSIX compliant shells.
In [t]csh you can use $argv[*]:q instead of "$@".
Watch out though, when using the form
  csh -c cmd args...
positional parameters are assigned starting from 1 and not from 0 as with sh, so you need to change the command line [1] or skip the first argument [2]. The latter option avoids you to change your parameter array for exec with respect to the sh-form.

[1]  csh -c 'usercmd $argv[*]:q' userarg1 userarg2 ...
[2]  csh -c 'usercmd $argv[2-]:q' usercmd userarg1 userarg2 ...
Comment 9 Ian 2010-06-29 05:51:39 MDT
Any quoting you do is technically shell-specific as well, as is use of the '-c' flag, which need not be supported by the shell the target user has chosen.  (Given that a shell binary can be anything.)
Comment 10 Paolo Herms 2010-06-29 11:30:16 MDT
(In reply to comment #9)
Isn't this problem related to the -i option? So if you want to simulate an initial login, this should definitely be done by a real shell with the capability to launch other programs with some arguments. So you may just limit the -i option to known shells. The user can then do all the other stuff manually without the -i option.