summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/ChangeLog14
-rw-r--r--runtime/task_finder.c109
2 files changed, 93 insertions, 30 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 0b7559b9..cc8bf1b0 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,17 @@
+2008-05-28 David Smith <dsmith@redhat.com>
+
+ * task_finder.c (__stp_utrace_attach_match_filename): Added
+ register_p parameter, which is passed on to the callback. Only
+ adds death notification if register_p is 1. If register_p is 0,
+ removes death notification.
+ (__stp_utrace_attach_match_tsk): Moved code from
+ __stp_utrace_task_finder_report_clone that handles the details of
+ grabbing a task's path.
+ (__stp_utrace_task_finder_report_clone): Calls new
+ __stp_utrace_attach_match_tsk().
+ (__stp_utrace_task_finder_report_exec): Notifies upper layer that
+ it might need to detach from newly exec'ed process.`
+
2008-05-27 Josh Stone <joshua.i.stone@intel.com>
PR 6432
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index a8de13d0..9b03234d 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -239,6 +239,7 @@ __stp_utrace_attach(struct task_struct *tsk,
static inline void
__stp_utrace_attach_match_filename(struct task_struct *tsk,
const char * const filename,
+ int register_p,
unsigned long event_flag)
{
size_t filelen;
@@ -272,8 +273,8 @@ __stp_utrace_attach_match_filename(struct task_struct *tsk,
continue;
if (cb_tgt->callback != NULL) {
- int rc = cb_tgt->callback(tsk, 1, event_flag,
- cb_tgt);
+ int rc = cb_tgt->callback(tsk, register_p,
+ event_flag, cb_tgt);
if (rc != 0) {
_stp_error("callback for %d failed: %d",
(int)tsk->pid, rc);
@@ -282,64 +283,102 @@ __stp_utrace_attach_match_filename(struct task_struct *tsk,
}
// Set up thread death notification.
- rc = __stp_utrace_attach(tsk, &cb_tgt->ops, cb_tgt,
- __STP_UTRACE_ATTACHED_TASK_EVENTS);
- if (rc != 0 && rc != EPERM)
- break;
- cb_tgt->engine_attached = 1;
+ if (register_p) {
+ rc = __stp_utrace_attach(tsk, &cb_tgt->ops,
+ cb_tgt,
+ __STP_UTRACE_ATTACHED_TASK_EVENTS);
+ if (rc != 0 && rc != EPERM)
+ break;
+ cb_tgt->engine_attached = 1;
+ }
+ else {
+ struct utrace_attached_engine *engine;
+ engine = utrace_attach(tsk,
+ UTRACE_ATTACH_MATCH_OPS,
+ &cb_tgt->ops, 0);
+ if (! IS_ERR(engine) && engine != NULL) {
+ utrace_detach(tsk, engine);
+ }
+ }
}
}
}
-static u32
-__stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine,
- struct task_struct *parent,
- unsigned long clone_flags,
- struct task_struct *child)
+// This function handles the details of getting a task's associated
+// pathname, and calling __stp_utrace_attach_match_filename() to
+// attach to it if we find the pathname "interesting". So, what's the
+// difference between path_tsk and match_tsk? Normally they are the
+// same, except in one case. In an UTRACE_EVENT(EXEC), we need to
+// detach engines from the newly exec'ed process (since its path has
+// changed). In this case, we have to match the path of the parent
+// (path_tsk) against the child (match_tsk).
+
+static void
+__stp_utrace_attach_match_tsk(struct task_struct *path_tsk,
+ struct task_struct *match_tsk, int register_p,
+ unsigned long event_flag)
{
- int rc;
struct mm_struct *mm;
char *mmpath_buf;
char *mmpath;
- if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING)
- return UTRACE_ACTION_RESUME;
+ if (path_tsk->pid <= 1 || match_tsk->pid <= 1)
+ return;
- // On clone, attach to the child.
- rc = __stp_utrace_attach(child, engine->ops, 0,
- __STP_UTRACE_TASK_FINDER_EVENTS);
- if (rc != 0 && rc != EPERM)
- return UTRACE_ACTION_RESUME;
-
- /* Grab the path associated with this task. */
- mm = get_task_mm(child);
+ /* Grab the path associated with the path_tsk. */
+ mm = get_task_mm(path_tsk);
if (! mm) {
/* If the thread doesn't have a mm_struct, it is
* a kernel thread which we need to skip. */
- return UTRACE_ACTION_RESUME;
+ return;
}
// Allocate space for a path
mmpath_buf = _stp_kmalloc(PATH_MAX);
if (mmpath_buf == NULL) {
+ mmput(mm);
_stp_error("Unable to allocate space for path");
- return UTRACE_ACTION_RESUME;
+ return;
}
// Grab the path associated with the new task
mmpath = __stp_get_mm_path(mm, mmpath_buf, PATH_MAX);
mmput(mm); /* We're done with mm */
if (mmpath == NULL || IS_ERR(mmpath)) {
- rc = -PTR_ERR(mmpath);
+ int rc = -PTR_ERR(mmpath);
_stp_error("Unable to get path (error %d) for pid %d",
- rc, (int)child->pid);
+ rc, (int)path_tsk->pid);
}
else {
- __stp_utrace_attach_match_filename(child, mmpath,
- UTRACE_EVENT(CLONE));
+ __stp_utrace_attach_match_filename(match_tsk, mmpath,
+ register_p, event_flag);
}
_stp_kfree(mmpath_buf);
+ return;
+}
+
+static u32
+__stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine,
+ struct task_struct *parent,
+ unsigned long clone_flags,
+ struct task_struct *child)
+{
+ int rc;
+ struct mm_struct *mm;
+ char *mmpath_buf;
+ char *mmpath;
+
+ if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING)
+ return UTRACE_ACTION_RESUME;
+
+ // On clone, attach to the child.
+ rc = __stp_utrace_attach(child, engine->ops, 0,
+ __STP_UTRACE_TASK_FINDER_EVENTS);
+ if (rc != 0 && rc != EPERM)
+ return UTRACE_ACTION_RESUME;
+
+ __stp_utrace_attach_match_tsk(parent, child, 1, UTRACE_EVENT(CLONE));
return UTRACE_ACTION_RESUME;
}
@@ -357,11 +396,21 @@ __stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine,
if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING)
return UTRACE_ACTION_RESUME;
+ // When exec'ing, we need to let callers detach from the
+ // parent thread (if necessary). For instance, assume
+ // '/bin/bash' clones and then execs '/bin/ls'. If the user
+ // was probing '/bin/bash', the cloned thread is still
+ // '/bin/bash' up until the exec.
+ if (tsk != NULL && tsk->parent != NULL && tsk->parent->pid > 1) {
+ __stp_utrace_attach_match_tsk(tsk->parent, tsk, 0,
+ UTRACE_EVENT(EXEC));
+ }
+
// On exec, check bprm
if (bprm->filename == NULL)
return UTRACE_ACTION_RESUME;
- __stp_utrace_attach_match_filename(tsk, bprm->filename,
+ __stp_utrace_attach_match_filename(tsk, bprm->filename, 1,
UTRACE_EVENT(EXEC));
return UTRACE_ACTION_RESUME;