mailing list of musl libc
 help / color / mirror / code / Atom feed
* Re: Hangup calling setuid() from vfork() child
@ 2019-09-30 19:57 Joshua Hudson
  2019-09-30 20:24 ` Markus Wichmann
  2019-09-30 20:27 ` Szabolcs Nagy
  0 siblings, 2 replies; 8+ messages in thread
From: Joshua Hudson @ 2019-09-30 19:57 UTC (permalink / raw)
  To: musl

>It's simpler than that. The (retired) specification for vfork did not
>allow anything but _exit or execve in the child after vfork, so the
>issue doesn't arise and it works perfectly fine with threads as long
>as you follow the requirement.

I'm reading the man page for vfork and it says what it actually does, that
is overlay the child process on the memory of the calling process.

posix_spawn can't be used in the originating location, and fork() is
hogging too much memory.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Re: Hangup calling setuid() from vfork() child
  2019-09-30 19:57 Hangup calling setuid() from vfork() child Joshua Hudson
@ 2019-09-30 20:24 ` Markus Wichmann
  2019-09-30 20:27 ` Szabolcs Nagy
  1 sibling, 0 replies; 8+ messages in thread
From: Markus Wichmann @ 2019-09-30 20:24 UTC (permalink / raw)
  To: musl

On Mon, Sep 30, 2019 at 12:57:34PM -0700, Joshua Hudson wrote:
> >It's simpler than that. The (retired) specification for vfork did not
> >allow anything but _exit or execve in the child after vfork, so the
> >issue doesn't arise and it works perfectly fine with threads as long
> >as you follow the requirement.

I remembered that while making dinner (after sending my first response).

>
> I'm reading the man page for vfork and it says what it actually does, that
> is overlay the child process on the memory of the calling process.
>

I don't know about you, but my manpage quite clearly states that vfork()
is equivalent to clone(CLONE_VM | CLONE_VFORK | SIGCHLD), that is:
Parent and child share memory, parent (only the calling thread) is
suspended until child execs or exits, and when it does, the child gets a
SIGCHLD.

If the child process changes anything in memory, that is reflected in
the parent. Basically, the vfork() child is in an invalid state and this
cannot be repaired without damaging the parent.

> posix_spawn can't be used in the originating location, and fork() is
> hogging too much memory.

fork() only "hogs" that memory which either parent or child modify
afterwards. You wish to use vfork(), so I guess the child process won't
go long before either exec or exit(), right? So you might want to enable
memory overcommit.

I don't know about your application, but your options are:

- Decouple the child part into another program proper, and use
  posix_spawn() to call it.
- Use fork() and eat the memory cost.
- Use clone() and eat the non-portability. Note that clone(CLONE_VFORK)
  has identical semantics to vfork(), so no calling setuid() there,
  either.

Ciao,
Markus


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Re: Hangup calling setuid() from vfork() child
  2019-09-30 19:57 Hangup calling setuid() from vfork() child Joshua Hudson
  2019-09-30 20:24 ` Markus Wichmann
@ 2019-09-30 20:27 ` Szabolcs Nagy
  1 sibling, 0 replies; 8+ messages in thread
From: Szabolcs Nagy @ 2019-09-30 20:27 UTC (permalink / raw)
  To: musl

* Joshua Hudson <joshudson@gmail.com> [2019-09-30 12:57:34 -0700]:
> >It's simpler than that. The (retired) specification for vfork did not
> >allow anything but _exit or execve in the child after vfork, so the
> >issue doesn't arise and it works perfectly fine with threads as long
> >as you follow the requirement.
> 
> I'm reading the man page for vfork and it says what it actually does, that
> is overlay the child process on the memory of the calling process.

the internals don't matter, the interface contract is
that you can only call exec* or _exit in the child.

> 
> posix_spawn can't be used in the originating location, and fork() is

why?

> hogging too much memory.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Hangup calling setuid() from vfork() child
@ 2019-09-30 20:45 Joshua Hudson
  0 siblings, 0 replies; 8+ messages in thread
From: Joshua Hudson @ 2019-09-30 20:45 UTC (permalink / raw)
  To: musl

> Basically, the vfork() child is in an invalid state and this cannot be repaired without damaging the parent.

Works on glibc just fine.

setuid() is on the list of signal-safe functions.

http://man7.org/linux/man-pages/man7/signal-safety.7.html

How about you call getpid() and check if you're on the process you
think you're on before calling __synccall? Somebody else might have
done syscall(SYS_fork).

> So you might want to enable memory overcommit.

I'm tired of paying the page fault penalty in the parent. It has a
majority of system RAM, and most of the pages are CoW long after the
vfork child hits execve.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Hangup calling setuid() from vfork() child
  2019-09-30 17:39 ` Markus Wichmann
@ 2019-09-30 17:43   ` Rich Felker
  0 siblings, 0 replies; 8+ messages in thread
From: Rich Felker @ 2019-09-30 17:43 UTC (permalink / raw)
  To: musl

On Mon, Sep 30, 2019 at 07:39:28PM +0200, Markus Wichmann wrote:
> On Mon, Sep 30, 2019 at 08:29:16AM -0700, Joshua Hudson wrote:
> > If there is more than one thread and vfork() calls setuid(), musl libc hangs up.
> >
> > void *thfunction(void*ig) {sleep(1000);returnNULL;}
> >
> > int main()
> > {
> >     pthread_t id;
> >     pthread_create(&id, NULL, thfunction, NULL);
> >     if (vfork() == 0) {
> >         setuid(0); /* hangup */
> >         _exit(0);
> >     }
> > }
> 
> That is an interesting interaction between threads and vfork().
> 
> The child process has only one thread, but it doesn't know that. It also
> can't write it down, since it is sharing memory with the parent (it
> would overwrite the parent's variables).
> 
> POSIX no longer defines vfork(), and therefore does not define any
> safety attributes for it. Is it reasonable to define vfork() as unusable
> in a multithreaded process? Calling something as intricate as
> __synccall() in a vfork() child is going to corrupt memory on a large
> scale.

It's simpler than that. The (retired) specification for vfork did not
allow anything but _exit or execve in the child after vfork, so the
issue doesn't arise and it works perfectly fine with threads as long
as you follow the requirement.

> posix_spawn() circumvents the problem by calling the system calls
> directly, BTW.

Yes, posix_spawn should be used if possible. It even has an attribute
to reset ids to the real ones.

Rich


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Hangup calling setuid() from vfork() child
  2019-09-30 15:29 Joshua Hudson
  2019-09-30 17:39 ` Markus Wichmann
@ 2019-09-30 17:41 ` Rich Felker
  1 sibling, 0 replies; 8+ messages in thread
From: Rich Felker @ 2019-09-30 17:41 UTC (permalink / raw)
  To: musl

On Mon, Sep 30, 2019 at 08:29:16AM -0700, Joshua Hudson wrote:
> If there is more than one thread and vfork() calls setuid(), musl libc hangs up.
> 
> void *thfunction(void*ig) {sleep(1000);returnNULL;}
> 
> int main()
> {
>     pthread_t id;
>     pthread_create(&id, NULL, thfunction, NULL);
>     if (vfork() == 0) {
>         setuid(0); /* hangup */
>         _exit(0);
>     }
> }

This is expected; the only legal action after vfork is _exit or
execve. In practice you could probably get by with
syscall(SYS_setuid,0) or similar in the child, but this isn't
supported usage and the specification for vfork has always been clear
that you can't do arbitrary stuff in the child. If you need to, you
should be using fork.

Rich


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Hangup calling setuid() from vfork() child
  2019-09-30 15:29 Joshua Hudson
@ 2019-09-30 17:39 ` Markus Wichmann
  2019-09-30 17:43   ` Rich Felker
  2019-09-30 17:41 ` Rich Felker
  1 sibling, 1 reply; 8+ messages in thread
From: Markus Wichmann @ 2019-09-30 17:39 UTC (permalink / raw)
  To: musl

On Mon, Sep 30, 2019 at 08:29:16AM -0700, Joshua Hudson wrote:
> If there is more than one thread and vfork() calls setuid(), musl libc hangs up.
>
> void *thfunction(void*ig) {sleep(1000);returnNULL;}
>
> int main()
> {
>     pthread_t id;
>     pthread_create(&id, NULL, thfunction, NULL);
>     if (vfork() == 0) {
>         setuid(0); /* hangup */
>         _exit(0);
>     }
> }

That is an interesting interaction between threads and vfork().

The child process has only one thread, but it doesn't know that. It also
can't write it down, since it is sharing memory with the parent (it
would overwrite the parent's variables).

POSIX no longer defines vfork(), and therefore does not define any
safety attributes for it. Is it reasonable to define vfork() as unusable
in a multithreaded process? Calling something as intricate as
__synccall() in a vfork() child is going to corrupt memory on a large
scale.

posix_spawn() circumvents the problem by calling the system calls
directly, BTW.

Ciao,
Markus


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Hangup calling setuid() from vfork() child
@ 2019-09-30 15:29 Joshua Hudson
  2019-09-30 17:39 ` Markus Wichmann
  2019-09-30 17:41 ` Rich Felker
  0 siblings, 2 replies; 8+ messages in thread
From: Joshua Hudson @ 2019-09-30 15:29 UTC (permalink / raw)
  To: musl

If there is more than one thread and vfork() calls setuid(), musl libc hangs up.

void *thfunction(void*ig) {sleep(1000);returnNULL;}

int main()
{
    pthread_t id;
    pthread_create(&id, NULL, thfunction, NULL);
    if (vfork() == 0) {
        setuid(0); /* hangup */
        _exit(0);
    }
}


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-09-30 20:45 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-30 19:57 Hangup calling setuid() from vfork() child Joshua Hudson
2019-09-30 20:24 ` Markus Wichmann
2019-09-30 20:27 ` Szabolcs Nagy
  -- strict thread matches above, loose matches on Subject: below --
2019-09-30 20:45 Joshua Hudson
2019-09-30 15:29 Joshua Hudson
2019-09-30 17:39 ` Markus Wichmann
2019-09-30 17:43   ` Rich Felker
2019-09-30 17:41 ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).