--On Tuesday, October 28, 2008 05:04:25 PM -0700 Sumanth Naropanth 
<Sumanth.Naropanth at Sun.COM> wrote:

>>> ease of use as the system(3C), by defining a single (const char *)
>>> argument. The implementation will be a wrapper around the
>>> posix_spawn(3C)/waitpid(3C) functions. This interface will provide
>>> greater security in comparison with the system() function by avoiding
>>> shell invocation. Quoted arguments will be supported by using a new
>>> macro called 'ES_QUOTE', which will be defined as:
>>>
>>>       # define ES_QUOTE      '\377%s\377'
>>>
>>> The special character '\377' is chosen since it lies outside the
>>> printable character set. This quoting mechanism will make it harder for
>>
>> Is that true for *every* character set and encoding scheme that we
>> support or might support?  It's true for US-ASCII and for UTF-8, for
>> example, but not for ISO8859-1, for example.
>>
>
> I agree that it's not impossible to supply '\377' as an input when some
> encoding schemes may allow for it. Using '\377' makes it much harder
> (but not completely impossible) to trick the argument parsing than using
> single/double quotes.

No, you're missing the point.  The statement "it lies outside the printable 
character set" is true for US-ASCII, but it is simply not true for every 
character set.  In ISO8859-1, to use Nico's example, '\377' is '?' 
(U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS).  Proposing that this 
character be used for quoting arguments suggests that you have not 
considered the i18n implications.




>> So this is likely a terrible choice of quote character.  Perhaps the
>> only safe quote character would be NUL, and then you'd need to use NUL
>> NUL as the terminator (or something).

That would preclude using the empty string as an argument.

>> Moreover, why even have a quote character?  Make this function take a
>> variable number of arguments, with the last being NULL, and be done.
>>
>
> Sounds like a good idea, but that pulls it away from a simple (const
> char *) interface. I'll give this more thought. Thanks!

The single-string interface is too simple to reliably do anything other 
than run a program with no arguments.  Any attempt to encode arguments in 
the same string will end up being inadequate, too complex, or both.  I 
think Nico is on the right track; give this thing the same interface as 
execl(), but with the fork-and-wait semantics of system.

I'd also consider whether you want an interface like that of execve(), 
which takes a char ** rather than a variable number of char * arguments, 
and/or a variant that accepts a single va_list instead of a variable number 
of arguments, to make it easier to write wrappers.

>>> When used inside a setuid program, the exec_system() function will drop
>>> privileges to those of the real user while executing the file/command.
>>
>> Maybe the user ID (real or effective) to use should be an argument, as
>> well as whether to drop privs.
>>
>
> This feature mimics the behavior of system(3C) when it's used inside
> setuid program.

Really?  system(3C) changes its UID before running a command?
Not according to the man page on my machine.



>>> The exec_system() implementation will extend the signal handling model
>>> of system(3C) and will set SIGCHLD to be blocked for the calling thread,
>>
>> Why not use forkx() to avoid SIGCHLD issues altogether?
>>
>
> Using posix_spawn()/waitpid() allows me to pass the return value of the
> execve() call back to the parent process when exec fails. I don't
> suppose forkx()/exec() will allow for that (apart from just causing the
> child to exit(127))?

Even with posix_spawn(), you might still end up with a failure in which the 
child exits with 127.  So, callers of your new interface will need to be 
prepared for that.

Reply via email to