posix_spawn(): errno in older glibc versions

Adhemerval Zanella adhemerval.zanella@linaro.org
Mon Mar 4 20:46:00 GMT 2019



On 04/03/2019 10:04, Felipe Gasper wrote:
> 
>> On Mar 4, 2019, at 2:59 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * Felipe Gasper:
>>
>>> The clone()d process (which is a CLONE_VFORK) also, per strace, does a
>>> whole mess of signal-setting prior to the execve(). This also appears
>>> to violate vfork()’s documentation.
>>
>> How so?
> 
> vfork’s man page says that only _exit or an exec function should follow the vfork in the child process, but I see a bunch of signal-handling calls in the child before the exec.
> 
> I guess this is another case of just knowing that it’s ok with the tested versions of Linux’s kernel?

I tried add to some information while writing the new posix_spawn regarding
how glibc uses clone (CLONE_VFORK) [1] in a safe way and why vfork is a
quite bad interface.  Also, Rich Felker has written a post why vfork
is considered harmful [2].

Basically the way Linux posix_spawn uses clone (CLONE_VFORK) is by:

  1. Allocate and providing its own stack for the new process. It avoid
     potentially spilled information from the register in the stack
     after the vfork call.

  2. No signal handlers must run in child context, to avoid corrupt
     parent's state. We block all signals (__libc_signal_block_all)
     including the internal ones meant for cancellation and setXuid.

  3. Child must synchronize with parent to enforce stack deallocation 
     and to possible return execv issues. This is done by the kernel
     that enforces that a new process created with clone (CLONE_VFORK)
     suspends the child executions and only resumes it when it exits
     by either a _exit or a execve.

Man-pages description of vfork [3] describes why vfork itself should
not be used (on 'Caveats' part):

"The  child  process  should  take  care  not  to modify the memory 
in unintended ways, since such changes will be seen by the parent 
process once the child terminates or executes another program.  In 
this regard, signal handlers can be especially problematic:"

And since glibc does not allow changing the signal handle for internal
signals, there is not safe way to prevent such issues (a program still
can call sigprocmask directly with syscall, but this comes with other
potential issues).

"When vfork() is called in a multithreaded process, only the calling 
thread is suspended until the child terminates or executes a new program.
 This means that the child is  sharing an address space with other 
running code.  This can be dangerous if another thread in the parent 
process changes credentials (using setuid(2) or similar), since there 
are now two processes with different privilege levels running in the 
same address space."

Unfortunately this is still and issue with posix_spawn [4] and I will
try to spend some time to see how to fix it.

So I think man-pages vfork description is pretty much accurate and there
is no need to change it. It states what vfork does, describes its history,
and its pitfalls. If I were to change anything it would be to add "do not
use this broken interface".

[1] https://sourceware.org/git/?p=glibc.git;a=commit;h=9ff72da471a509a8c19791efe469f47fa6977410
[2] https://ewontfix.com/7/
[3] https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/vfork.2
[4] https://sourceware.org/bugzilla/show_bug.cgi?id=14749

> 
>>
>>> Also, at least on the Ubuntu box, posix_spawn()’s man page appears to
>>> be incorrect:
>>>
>>> -----
>>>       The  posix_spawn()  and  posix_spawnp() functions fail only in the case
>>>       where the underlying fork(2) or vfork(2) call fails;  in  these  cases,
>>>       these functions return an error number, which will be one of the errors
>>>       described for fork(2) or vfork(2).
>>> -----
>>>
>>> From what I see, the clone() clearly succeeds, but it’s the exec’s
>>> success/failure that posix_spawn() reports. This is much more useful
>>> behavior, IMO--does that just need to make its way into the man page?
>>
>> Well, there is the matter of the emulations, where you do not actually
>> get a report of the execve error.  I'm not sure to what extent the
>> man-pages project intends to cover those.
> 
> All the same, the man page makes no mention of the (hugely preferable!) behaviour I’m seeing in the newer glibc.
> 
> I’d be happy to file a bug report against the man page but wasn’t successful in finding the repo to verify that the latest version hasn’t addressed this. If you know it off-hand, would you be able to share?

Check https://www.kernel.org/doc/man-pages/download.html

> 
> Thank you!
> 
> -FG
> 



More information about the Libc-help mailing list