2001-04-19 11:36:02

by Éric Brunet

[permalink] [raw]
Subject: Children first in fork

Hello all,

I have read on lwn.net that the patch that makes children run first after
a fork has been integrated in the latest pre-kernel.

I am a little bit concerned by that, as I have begun to write a program
that monitors process using ptrace. The difficulty is to ptrace-attach
the child in a fork before it can do anything unmonitored. When the
parent runs first, the return from the fork system called is trapped by
the monitor program which has enough time to ptrace-attach the child. If
the child runs first, it is not even remotely the case anymore.

I understand that performance is more important that the possibility to
ptrace across forks, but I still think that there should be a way to
attach the children of a ptraced-process. Is there currently a way to
achieve this in the kernel that I am not aware of ?

?ric Brunet


2001-04-19 12:07:45

by David Schwartz

[permalink] [raw]
Subject: RE: Children first in fork


> Hello all,
>
> I have read on lwn.net that the patch that makes children run first after
> a fork has been integrated in the latest pre-kernel.
>
> I am a little bit concerned by that, as I have begun to write a program
> that monitors process using ptrace. The difficulty is to ptrace-attach
> the child in a fork before it can do anything unmonitored. When the
> parent runs first, the return from the fork system called is trapped by
> the monitor program which has enough time to ptrace-attach the child. If
> the child runs first, it is not even remotely the case anymore.
>
> I understand that performance is more important that the possibility to
> ptrace across forks, but I still think that there should be a way to
> attach the children of a ptraced-process. Is there currently a way to
> achieve this in the kernel that I am not aware of ?

It seems to me that what you really want is a fork option to create the
child in a suspended state.

DS

2001-04-19 12:57:02

by Éric Brunet

[permalink] [raw]
Subject: Re: Children first in fork

In ens.mailing-lists.linux-kernel, you wrote:
> It seems to me that what you really want is a fork option to create the
>child in a suspended state.

Yes, or a clone option (using ptrace, I can always change on the fly
the fork system call into a clone system call and add whatever option I
want). But I would just like to be sure that there are no mechanism
already available by which it is possible to ptrace reliably a child.

?ric Brunet

2001-04-19 16:31:53

by Wichert Akkerman

[permalink] [raw]
Subject: Re: Children first in fork

In article <[email protected]>,
=?ISO-8859-1?Q?=C9ric?= Brunet <[email protected]> wrote:
>Yes, or a clone option (using ptrace, I can always change on the fly=20
>the fork system call into a clone system call and add whatever option I
>want).

Last time I tried that it didn't work since the kernel had already
grabbed the syscall number and the registers so I couldn't change it
anymore.

What you can do is what strace does: insert a loop instruction after
the fork or clone call and remove that when the call returns.

Wichert.


--
________________________________________________________________
/ Generally uninteresting signature - ignore at your convenience \
| [email protected] http://www.liacs.nl/~wichert/ |
| 1024D/2FA3BC2D 576E 100B 518D 2F16 36B0 2805 3CB8 9250 2FA3 BC2D |

2001-04-19 17:59:19

by Linus Torvalds

[permalink] [raw]
Subject: Re: Children first in fork

In article <[email protected]>,
Wichert Akkerman <[email protected]> wrote:
>
>What you can do is what strace does: insert a loop instruction after
>the fork or clone call and remove that when the call returns.

You're probably even better off just intercepting the fork, turning it
into a clone, and setting the CLONE_PTRACE option. Which (together with
tracing the parent, which you will obviously be doing already in order
to do all this in the first place) will nicely cause the child to get an
automatic SIGSTOP _and_ be already traced.

Not that I've tested it myself.

Linus

2001-04-20 07:47:25

by Wichert Akkerman

[permalink] [raw]
Subject: Re: Children first in fork

In article <[email protected]>,
Linus Torvalds <[email protected]> wrote:
>Not that I've tested it myself.

I did a few months ago, it didn't work.

Wichert.
--
________________________________________________________________
/ Generally uninteresting signature - ignore at your convenience \
| [email protected] http://www.liacs.nl/~wichert/ |
| 1024D/2FA3BC2D 576E 100B 518D 2F16 36B0 2805 3CB8 9250 2FA3 BC2D |

2001-04-20 10:13:26

by Éric Brunet

[permalink] [raw]
Subject: Re: Children first in fork

In ens.mailing-lists.linux-kernel, you wrote:
>You're probably even better off just intercepting the fork, turning it
>into a clone, and setting the CLONE_PTRACE option. Which (together with
>tracing the parent, which you will obviously be doing already in order
>to do all this in the first place) will nicely cause the child to get an
>automatic SIGSTOP _and_ be already traced.

Well, I tried that, and it doesn't work. The problem is that the child
starts ptraced, but it is its parent that will receive a signal for each
syscall, and not the program that ptraces its parent. Of course, the
parent will probably be a little bit confused by that (as it doesn't expect
to receive those signals) and the monitoring programm won't see anything.

Maybe it would work if the function copy_flags in fork.c was modified
into:
-----------------------------------------------------------------
--- fork-old.c Fri Apr 20 12:01:09 2001
+++ fork.c Fri Apr 20 12:05:57 2001
@@ -552,8 +552,14 @@

new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK);
new_flags |= PF_FORKNOEXEC;
- if (!(clone_flags & CLONE_PTRACE))
+ if (!(clone_flags & CLONE_PTRACE)) {
new_flags &= ~(PF_PTRACED|PF_TRACESYS);
+ if (p->p_pptr->flags &= PF_PTRACED) {
+ REMOVE_LINKS(p);
+ p->p_pptr = p->p_pptr->p_pptr;
+ SET_LINKS(child);
+ }
+ }
if (clone_flags & CLONE_VFORK)
new_flags |= PF_VFORK;
p->flags = new_flags;
-----------------------------------------------------------------
(sorry, it is a 2.2.19pre8 kernel, and I don't know what have changed
since in that file)
Ok, I haven't tried it (can't reboot a machine now), and I don't know
what I am talking about, but the idea is simply ``if CLONE_PTRACE is set,
and the parent is ptraced, then the child's effective parent should be
its grandfather.''

Was it the way it was intended to work ? As it is now, I don't see any
use of the CLONE_PTRACE flag.

?ric Brunet

2001-04-20 10:27:27

by Thomas Pornin

[permalink] [raw]
Subject: Re: Children first in fork

In article <[email protected]> you write:
> You're probably even better off just intercepting the fork, turning it
> into a clone, and setting the CLONE_PTRACE option.

Actually it is not that simple. The child process will be traced by its
father, not the tracing program. The father must detach from its child
in order to allow the tracing program to attach to the child, and then
you have again the race condition: the child will be untraced for some
time.

The trick is to modify the return address of the call so that the child
and the father loop on the syscall. This way, you can make the father:

-- modify the child so that the child will send itself a SIGSTOP when
released
-- detach itself from the child
(-- if the child is scheduled, it stops itself)
Then the tracing process can attach to the child and handle the
situation.

I have some code almost running, doing that. Well, it works, but with
strange bugs in some occasions. I am still sorting these out. It is
utterly tricky, anyway.


--Thomas Pornin

2001-04-20 14:58:36

by Mark Kettenis

[permalink] [raw]
Subject: Re: Children first in fork

The behaviour of CLONE_PTRACE in Linux 2.4.x is different from the
behaviour in 2.2.x. Linus is describing the 2.4.x. behaviour, where
the program that's doing the tracing will get the events instead of
the "real" parent. I believe the 2.2.x behaviour was pretty much
useless, and IIRC that was the reason that Linus accepted a patch for
the new behaviour. I've tested CLONE_PTRACE in the sense that the
development version of GDB contains some code that allows debugging of
any clone() based thread stuff if the threads implementationion
specifies CLONE_PTRACE in its clone() calls. That way GDB notices new
threads automagically. It only works on Linux 2.4.x of course, and I
still have to hack something up to make this functionality in GDB
available to the user.

Mark

2001-04-20 17:49:05

by Linus Torvalds

[permalink] [raw]
Subject: Re: Children first in fork



On Fri, 20 Apr 2001, Xric Brunet wrote:
>
> Well, I tried that, and it doesn't work.

I think you're using a buggy 2.2.x kernel. 2.4.x should do this right.
Please give it a whirl.

Linus

2001-04-20 17:51:26

by Linus Torvalds

[permalink] [raw]
Subject: Re: Children first in fork



On Fri, 20 Apr 2001, Mark Kettenis wrote:
> I believe the 2.2.x behaviour was pretty much
> useless,

No. 2.2.x is not useless, it is apparently _buggy_ in this regard. Some of
the fixes in the 2.3.x timeframe seem to not have made it into 2.2.x.

Linus