[PATCH 47] mv task_struct->last_siginfo ptrace_context->siginfo

Oleg Nesterov oleg at redhat.com
Thu Sep 17 19:08:21 UTC 2009


Introduce ptrace_context->siginfo. Of course the usage of context->siginfo
is still wrong. But this change is important, previously PTRACE_DETACH can
leave the tracee with ->last_siginfo != NULL.

ptrace_getsiginfo/ptrace_setsiginfo need cleanups (and fixes). I think we
need ptrace_lookup_engine() helper, and ptrace_request() should find the
engine and pass it to ptrace_resume/etc.

---

 kernel/ptrace.c |   38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

--- PU/kernel/ptrace.c~47_CTX_SIGINFO	2009-09-17 19:33:34.000000000 +0200
+++ PU/kernel/ptrace.c	2009-09-17 20:13:24.000000000 +0200
@@ -38,6 +38,8 @@ struct ptrace_event {
 struct ptrace_context {
 	int options;
 
+	siginfo_t *siginfo;
+
 	struct ptrace_event ev_array[2];
 	unsigned int ev_first, ev_last;
 };
@@ -319,7 +321,7 @@ static u32 ptrace_report_exec(enum utrac
 static void ptrace_resume_signal(struct utrace_engine *engine,
 					struct task_struct *tracee, long data)
 {
-	siginfo_t *info = tracee->last_siginfo;
+	siginfo_t *info = ptrace_context(engine)->siginfo;
 
 	if (WARN_ON(!info))
 		return;
@@ -355,12 +357,12 @@ static u32 ptrace_report_signal(u32 acti
 	case UTRACE_SIGNAL_HANDLER:
 		WARN_ON(1);
 	case UTRACE_SIGNAL_REPORT:
-		if (!task->last_siginfo)
+		if (!context->siginfo)
 			return UTRACE_RESUME | UTRACE_SIGNAL_IGN;
 
-		if (WARN_ON(task->last_siginfo != info))
+		if (WARN_ON(context->siginfo != info))
 			return UTRACE_RESUME | UTRACE_SIGNAL_IGN;
-		task->last_siginfo = NULL;
+		context->siginfo = NULL;
 
 		if (!info->si_signo) // debugger cancelled sig
 			return UTRACE_RESUME | UTRACE_SIGNAL_IGN;
@@ -379,10 +381,10 @@ static u32 ptrace_report_signal(u32 acti
 		return UTRACE_RESUME | UTRACE_SIGNAL_DELIVER;
 
 	default:
-		WARN_ON(task->last_siginfo);
-		task->last_siginfo = info;
+		WARN_ON(context->siginfo);
+		context->siginfo = info;
 		// Make sure the next UTRACE_SIGNAL_REPORT
-		// will clear ->last_siginfo
+		// will clear context->siginfo
 		utrace_control(task, engine, UTRACE_INTERRUPT);
 
 		ev = ev_push(context);
@@ -817,33 +819,47 @@ static int ptrace_set_options(struct tas
 
 static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
 {
+	struct utrace_engine *engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS,
+								&ptrace_utrace_ops, NULL);
 	unsigned long flags;
 	int error = -ESRCH;
 
+	if (IS_ERR(engine))
+		return error;
+
 	if (lock_task_sighand(child, &flags)) {
 		error = -EINVAL;
-		if (likely(child->last_siginfo != NULL)) {
-			*info = *child->last_siginfo;
+		if (likely(ptrace_context(engine)->siginfo != NULL)) {
+			*info = *ptrace_context(engine)->siginfo;
 			error = 0;
 		}
 		unlock_task_sighand(child, &flags);
 	}
+
+	utrace_engine_put(engine);
 	return error;
 }
 
 static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
 {
+	struct utrace_engine *engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS,
+								&ptrace_utrace_ops, NULL);
 	unsigned long flags;
 	int error = -ESRCH;
 
+	if (IS_ERR(engine))
+		return error;
+
 	if (lock_task_sighand(child, &flags)) {
 		error = -EINVAL;
-		if (likely(child->last_siginfo != NULL)) {
-			*child->last_siginfo = *info;
+		if (likely(ptrace_context(engine)->siginfo != NULL)) {
+			*ptrace_context(engine)->siginfo = *info;
 			error = 0;
 		}
 		unlock_task_sighand(child, &flags);
 	}
+
+	utrace_engine_put(engine);
 	return error;
 }
 




More information about the utrace-devel mailing list