Re: [ptrace] please review follow fork/exec changes

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Thu, 9 Feb 2012 14:29:08 +0200
On Wed, Feb 08, 2012 at 04:51:57PM -0800, Dmitry Mikulin wrote:
> The patch I sent earlier works for me. Just wanted to let you know to 
> illustrate what I would like to see from the kernel.
> 
> I'm trying to see if there's way not to add flags with semantics similar to 
> TDB_EXEC. I think the problem with TDB_EXEC is that is serves a trigger for 
> a stop as well as an indicator to return PL_FLAG_EXEC. And in my case I 
> still want to see all the stops but I only want to see the PL_FLAG_EXEC 
> when PT_FOLLOW_EXEC is specified.
> 
> Do you think the attached patch will do what I'd like without compromising 
> existing functionality?
> 
The semantic of PL_FLAG_EXEC up until now is very simple: it indicates
that current stop occured during the first return to usermode after
successful exec. The proposed patch breaks the semantic, because now
some stops which satisfy the stated condition are no longer marked with
the flag.

That said, I am lost. You stated that you still need some stops at
exec even when not PT_FOLLOW_EXEC is requested. Why usermode cannot
remember whether the PT_FOLLOW_EXEC was set for the process, and ignore
PL_FLAG_EXEC if not requested ?

I just gave up and added PL_FLAG_EXECF, which is set when PT_FOLLOW_EXEC
was set and exec is active. Would this work for your purposes ?
PL_FLAG_EXECF has the same semantic as PL_FLAG_EXEC had in your
follow-exec.patch. But the stop set is not changed comparing with the
stock src.

Are you fine with PL_FLAG_CHILD part of the changes ? If yes, I will
commit it to make some progress.

diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 60639c9..e447c93 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
_at__at_ -1035,7 +1035,9 _at__at_ fork_return(struct thread *td, struct trapframe *frame)
 			p->p_oppid = p->p_pptr->p_pid;
 			proc_reparent(p, dbg);
 			sx_xunlock(&proctree_lock);
+			td->td_dbgflags |= TDB_CHILD;
 			ptracestop(td, SIGSTOP);
+			td->td_dbgflags &= ~TDB_CHILD;
 		} else {
 			/*
 			 * ... otherwise clear the request.
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 4510380..4f93a79 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
_at__at_ -660,6 +660,7 _at__at_ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
 	case PT_TO_SCX:
 	case PT_SYSCALL:
 	case PT_FOLLOW_FORK:
+	case PT_FOLLOW_EXEC:
 	case PT_DETACH:
 		sx_xlock(&proctree_lock);
 		proctree_locked = 1;
_at__at_ -873,6 +874,12 _at__at_ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
 		else
 			p->p_flag &= ~P_FOLLOWFORK;
 		break;
+	case PT_FOLLOW_EXEC:
+		if (data)
+			p->p_flag |= P_FOLLOWEXEC;
+		else
+			p->p_flag &= ~P_FOLLOWEXEC;
+		break;
 
 	case PT_STEP:
 	case PT_CONTINUE:
_at__at_ -936,7 +943,8 _at__at_ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
 					p->p_sigparent = SIGCHLD;
 			}
 			p->p_oppid = 0;
-			p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
+			p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK |
+			    P_FOLLOWEXEC);
 
 			/* should we send SIGCHLD? */
 			/* childproc_continued(p); */
_at__at_ -1139,12 +1147,17 _at__at_ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
 			pl->pl_flags |= PL_FLAG_SCE;
 		else if (td2->td_dbgflags & TDB_SCX)
 			pl->pl_flags |= PL_FLAG_SCX;
-		if (td2->td_dbgflags & TDB_EXEC)
+		if (td2->td_dbgflags & TDB_EXEC) {
 			pl->pl_flags |= PL_FLAG_EXEC;
+			if (p->p_flag & P_FOLLOWEXEC)
+				pl->pl_flags |= PL_FLAG_EXECF;
+		}
 		if (td2->td_dbgflags & TDB_FORK) {
 			pl->pl_flags |= PL_FLAG_FORKED;
 			pl->pl_child_pid = td2->td_dbg_forked;
 		}
+		if (td2->td_dbgflags & TDB_CHILD)
+			pl->pl_flags |= PL_FLAG_CHILD;
 		pl->pl_sigmask = td2->td_sigmask;
 		pl->pl_siglist = td2->td_siglist;
 		strcpy(pl->pl_tdname, td2->td_name);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 9ebfe83..bec7223 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
_at__at_ -384,6 +384,7 _at__at_ do {									\
 				      process */
 #define	TDB_STOPATFORK	0x00000080 /* Stop at the return from fork (child
 				      only) */
+#define	TDB_CHILD	0x00000100 /* New child indicator for ptrace() */
 
 /*
  * "Private" flags kept in td_pflags:
_at__at_ -613,6 +614,7 _at__at_ struct proc {
 #define	P_HWPMC		0x800000 /* Process is using HWPMCs */
 
 #define	P_JAILED	0x1000000 /* Process is in jail. */
+#define	P_FOLLOWEXEC	0x2000000 /* Report execs with ptrace. */
 #define	P_INEXEC	0x4000000 /* Process is in execve(). */
 #define	P_STATCHILD	0x8000000 /* Child process stopped or exited. */
 #define	P_INMEM		0x10000000 /* Loaded into memory. */
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index 2583d59..81cebfc 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
_at__at_ -64,6 +64,7 _at__at_
 #define	PT_SYSCALL	22
 
 #define	PT_FOLLOW_FORK	23
+#define	PT_FOLLOW_EXEC	24
 
 #define PT_GETREGS      33	/* get general-purpose registers */
 #define PT_SETREGS      34	/* set general-purpose registers */
_at__at_ -100,13 +101,15 _at__at_ struct ptrace_lwpinfo {
 #define	PL_EVENT_NONE	0
 #define	PL_EVENT_SIGNAL	1
 	int	pl_flags;	/* LWP flags. */
-#define	PL_FLAG_SA	0x01	/* M:N thread */
-#define	PL_FLAG_BOUND	0x02	/* M:N bound thread */
-#define	PL_FLAG_SCE	0x04	/* syscall enter point */
-#define	PL_FLAG_SCX	0x08	/* syscall leave point */
-#define	PL_FLAG_EXEC	0x10	/* exec(2) succeeded */
-#define	PL_FLAG_SI	0x20	/* siginfo is valid */
-#define	PL_FLAG_FORKED	0x40	/* new child */
+#define	PL_FLAG_SA	0x0001	/* M:N thread */
+#define	PL_FLAG_BOUND	0x0002	/* M:N bound thread */
+#define	PL_FLAG_SCE	0x0004	/* syscall enter point */
+#define	PL_FLAG_SCX	0x0008	/* syscall leave point */
+#define	PL_FLAG_EXEC	0x0010	/* exec(2) succeeded */
+#define	PL_FLAG_SI	0x0020	/* siginfo is valid */
+#define	PL_FLAG_FORKED	0x0040	/* child born */
+#define	PL_FLAG_CHILD	0x0080	/* I am from child */
+#define	PL_FLAG_EXECF	0x0100	/* exec and PT_FOLLOW_EXEC was set */
 	sigset_t	pl_sigmask;	/* LWP signal mask */
 	sigset_t	pl_siglist;	/* LWP pending signal */
 	struct __siginfo pl_siginfo;	/* siginfo for signal */



Received on Thu Feb 09 2012 - 11:29:21 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:23 UTC