Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kerneltoast/10e6ffdecac6510818324c4b7835fd9d to your computer and use it in GitHub Desktop.
Save kerneltoast/10e6ffdecac6510818324c4b7835fd9d to your computer and use it in GitHub Desktop.
utrace refcount
From b807d68401ccaf3c4ef17b89144ec2c58c9b081a Mon Sep 17 00:00:00 2001
From: Sultan Alsawaf <sultan@openresty.com>
Date: Fri, 5 Feb 2021 13:09:16 -0800
Subject: [PATCH 1/4] stp_utrace: remove outdated utrace_cleanup_lock comment
This lock doesn't exist anymore.
---
runtime/stp_utrace.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/runtime/stp_utrace.c b/runtime/stp_utrace.c
index 9cc910222..1e79ec52a 100644
--- a/runtime/stp_utrace.c
+++ b/runtime/stp_utrace.c
@@ -532,8 +532,6 @@ stp_task_notify_resume(struct task_struct *target, struct utrace *utrace)
/*
* Clean up everything associated with @task.utrace.
- *
- * This routine must be called under the utrace_cleanup_lock.
*/
static void utrace_cleanup(struct utrace *utrace)
{
--
2.30.0
From 109c51173a67373c604ee85ea15fd61215ce41c5 Mon Sep 17 00:00:00 2001
From: Sultan Alsawaf <sultan@openresty.com>
Date: Fri, 5 Feb 2021 13:22:16 -0800
Subject: [PATCH 2/4] stp_utrace: remove useless RCU read locks
These RCU read locks don't actually protect anything. The task struct
pointer is not actually dereferenced in get_utrace_lock(), and the RCU
read lock in utrace_reset() serves no purpose at all.
---
runtime/stp_utrace.c | 27 +++------------------------
1 file changed, 3 insertions(+), 24 deletions(-)
diff --git a/runtime/stp_utrace.c b/runtime/stp_utrace.c
index 1e79ec52a..581964289 100644
--- a/runtime/stp_utrace.c
+++ b/runtime/stp_utrace.c
@@ -1022,34 +1022,22 @@ static struct utrace *get_utrace_lock(struct task_struct *target,
struct utrace_bucket *bucket;
struct utrace *utrace;
- rcu_read_lock();
-
/*
- * If this engine was already detached, bail out before we look at
- * the task_struct pointer at all. If it's detached after this
- * check, then RCU is still keeping this task_struct pointer valid.
- *
* The ops pointer is NULL when the engine is fully detached.
* It's &utrace_detached_ops when it's marked detached but still
* on the list. In the latter case, utrace_barrier() still works,
* since the target might be in the middle of an old callback.
*/
- if (unlikely(!engine->ops)) {
- rcu_read_unlock();
+ if (unlikely(!engine->ops))
return ERR_PTR(-ESRCH);
- }
- if (unlikely(engine->ops == &utrace_detached_ops)) {
- rcu_read_unlock();
+ if (unlikely(engine->ops == &utrace_detached_ops))
return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS);
- }
bucket = get_utrace_bucket(target);
utrace = task_utrace_struct(bucket, target);
- if (unlikely(!utrace)) {
- rcu_read_unlock();
+ if (unlikely(!utrace))
return ERR_PTR(-ESRCH);
- }
spin_lock(&utrace->lock);
if (unlikely(utrace->reap) || unlikely(!engine->ops) ||
@@ -1063,7 +1051,6 @@ static struct utrace *get_utrace_lock(struct task_struct *target,
if (!attached && engine->ops == &utrace_detached_ops)
utrace = ERR_PTR(-ERESTARTSYS);
}
- rcu_read_unlock();
return utrace;
}
@@ -1346,15 +1333,7 @@ static bool utrace_reset(struct task_struct *task, struct utrace *utrace)
if (task_is_traced(task) && !(flags & ENGINE_STOP))
utrace_wakeup(task, utrace);
- /*
- * In theory spin_lock() doesn't imply rcu_read_lock().
- * Once we clear ->utrace_flags this task_struct can go away
- * because tracehook_prepare_release_task() path does not take
- * utrace->lock when ->utrace_flags == 0.
- */
- rcu_read_lock();
utrace->utrace_flags = flags;
- rcu_read_unlock();
spin_unlock(&utrace->lock);
put_detached_list(&detached);
--
2.30.0
From 420e39b7ad221382b4f1c674e926884dbc0bb21f Mon Sep 17 00:00:00 2001
From: Sultan Alsawaf <sultan@openresty.com>
Date: Fri, 5 Feb 2021 14:07:17 -0800
Subject: [PATCH 3/4] stp_utrace: always assume in_atomic() in
utrace_report_death()
As we've established in the past, in_atomic() only works when PREEMPT is
enabled. On non-PREEMPT kernels, in_atomic() will return false even when
used inside a spin-locked critical section. Therefore, in order to make
utrace_report_death() safe on all configurations, always use a task
worker to perform the report work.
---
runtime/stp_utrace.c | 49 ++++++++++++++------------------------------
1 file changed, 15 insertions(+), 34 deletions(-)
diff --git a/runtime/stp_utrace.c b/runtime/stp_utrace.c
index 581964289..869e41d78 100644
--- a/runtime/stp_utrace.c
+++ b/runtime/stp_utrace.c
@@ -2709,7 +2709,6 @@ static void utrace_report_death(void *cb_data __attribute__ ((unused)),
{
struct utrace_bucket *bucket;
struct utrace *utrace;
- INIT_REPORT(report);
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
@@ -2746,44 +2745,26 @@ static void utrace_report_death(void *cb_data __attribute__ ((unused)),
* flag and know that we are not yet fully quiescent for purposes
* of detach bookkeeping.
*/
- if (in_atomic() || irqs_disabled()) {
- if (atomic_add_unless(&utrace->report_work_added, 1, 1)) {
- int rc;
+ if (atomic_add_unless(&utrace->report_work_added, 1, 1)) {
+ int rc;
#ifdef STP_TF_DEBUG
- printk(KERN_ERR "%s:%d - adding task_work\n",
- __FUNCTION__, __LINE__);
+ printk(KERN_ERR "%s:%d - adding task_work\n",
+ __FUNCTION__, __LINE__);
#endif
- rc = stp_task_work_add(task,
- &utrace->report_work);
- if (rc != 0) {
- atomic_set(&utrace->report_work_added, 0);
- /* stp_task_work_add() returns -ESRCH
- * if the task has already passed
- * exit_task_work(). Just ignore this
- * error. */
- if (rc != -ESRCH) {
- printk(KERN_ERR
- "%s:%d - task_work_add() returned %d\n",
- __FUNCTION__, __LINE__, rc);
- }
+ rc = stp_task_work_add(task, &utrace->report_work);
+ if (rc != 0) {
+ atomic_set(&utrace->report_work_added, 0);
+ /* stp_task_work_add() returns -ESRCH
+ * if the task has already passed
+ * exit_task_work(). Just ignore this
+ * error. */
+ if (rc != -ESRCH) {
+ printk(KERN_ERR
+ "%s:%d - task_work_add() returned %d\n",
+ __FUNCTION__, __LINE__, rc);
}
}
}
- else {
- spin_lock(&utrace->lock);
- BUG_ON(utrace->death);
- utrace->death = 1;
- utrace->resume = UTRACE_RESUME;
- splice_attaching(utrace);
- spin_unlock(&utrace->lock);
-
- REPORT_CALLBACKS(, task, utrace, &report, UTRACE_EVENT(DEATH),
- report_death, engine, -1/*group_dead*/,
- -1/*signal*/);
-
- utrace_maybe_reap(task, utrace, false);
- utrace_free(bucket, utrace);
- }
}
/*
--
2.30.0
From 5d9d78b13c5eadabbeaff3d20778b49d032dacee Mon Sep 17 00:00:00 2001
From: Sultan Alsawaf <sultan@openresty.com>
Date: Fri, 5 Feb 2021 17:40:22 -0800
Subject: [PATCH 4/4] stp_utrace: fix widespread utrace struct use-after-free
-Cancel all the task workers that dereference the utrace struct
-Hold a task struct reference so utrace->task is always valid
-Use reference counts on the utrace struct itself
-Rename get_utrace_bucket() to find_utrace_bucket() since it doesn't
grab any references
-Rename task_utrace_struct() to get_utrace_struct() to indicate that it
grabs a reference on the returned utrace struct
---
runtime/stp_utrace.c | 471 ++++++++++++++++++++++++-------------------
1 file changed, 269 insertions(+), 202 deletions(-)
diff --git a/runtime/stp_utrace.c b/runtime/stp_utrace.c
index 869e41d78..ff8c5549d 100644
--- a/runtime/stp_utrace.c
+++ b/runtime/stp_utrace.c
@@ -121,7 +121,8 @@ struct utrace {
atomic_t report_work_added; /* called task_work_add() on
* 'report_work' */
- unsigned long utrace_flags;
+ atomic_t refcount;
+ unsigned int utrace_flags;
struct hlist_node hlist; /* task_utrace_table linkage */
struct task_struct *task;
@@ -446,7 +447,7 @@ error:
return rc;
}
-static void utrace_cleanup(struct utrace *utrace);
+static void utrace_cleanup(struct utrace_bucket *bucket, struct utrace *utrace);
static int utrace_exit(void)
{
@@ -480,11 +481,8 @@ static int utrace_exit(void)
rcu_read_lock();
stap_hlist_for_each_entry_rcu(utrace, node, &bucket->head, hlist) {
- stp_spin_lock_irqsave(&bucket->lock, flags);
- hlist_del_rcu(&utrace->hlist);
- stp_spin_unlock_irqrestore(&bucket->lock, flags);
-
- utrace_cleanup(utrace);
+ if (atomic_read(&utrace->refcount))
+ utrace_cleanup(bucket, utrace);
}
rcu_read_unlock();
}
@@ -513,8 +511,13 @@ static void
stp_task_notify_resume(struct task_struct *target, struct utrace *utrace)
{
if (atomic_add_unless(&utrace->resume_work_added, 1, 1)) {
- int rc = stp_task_work_add(target, &utrace->resume_work);
+ int rc;
+
+ /* Don't need to use utrace get/put because we have a ref */
+ atomic_inc(&utrace->refcount);
+ rc = stp_task_work_add(target, &utrace->resume_work);
if (rc != 0) {
+ atomic_dec(&utrace->refcount);
atomic_set(&utrace->resume_work_added, 0);
/* stp_task_work_add() returns -ESRCH if the
@@ -533,13 +536,21 @@ stp_task_notify_resume(struct task_struct *target, struct utrace *utrace)
/*
* Clean up everything associated with @task.utrace.
*/
-static void utrace_cleanup(struct utrace *utrace)
+static void utrace_cleanup(struct utrace_bucket *bucket, struct utrace *utrace)
{
struct utrace_engine *engine, *next;
+ unsigned long flags;
+
+ /* Remove this utrace from the mapping list of tasks to struct utrace */
+ stp_spin_lock_irqsave(&bucket->lock, flags);
+ hlist_del_rcu(&utrace->hlist);
+ stp_spin_unlock_irqrestore(&bucket->lock, flags);
+
+ /* Put the reference on the task struct */
+ put_task_struct(utrace->task);
/* Free engines associated with the struct utrace, starting
* with the 'attached' list then doing the 'attaching' list. */
- spin_lock(&utrace->lock);
list_for_each_entry_safe(engine, next, &utrace->attached, entry) {
#ifdef STP_TF_DEBUG
printk(KERN_ERR "%s:%d - removing engine\n",
@@ -553,7 +564,6 @@ static void utrace_cleanup(struct utrace *utrace)
list_del(&engine->entry);
_stp_kfree(engine);
}
- spin_unlock(&utrace->lock);
/* Note that we don't need to worry about
* utrace->resume_work_added and utrace->report_work_added,
@@ -573,28 +583,29 @@ static void utrace_syscall_exit_work(struct task_work *work);
static void utrace_exec_work(struct task_work *work);
static void utrace_clone_work(struct task_work *work);
-/* MACROS for utrace_cancel_all_task_work(): */
-#ifdef STP_TF_DEBUG
-#define CANCEL_IF_WORK(added_field, task_work_func) \
- if (atomic_add_unless(&added_field, \
- -1, 0)) { \
- if (stp_task_work_cancel(utrace->task, \
- &task_work_func) == NULL) \
- printk(KERN_ERR "%s:%d - task_work_cancel() failed for %s? task %p, %d, %s\n", \
- __FUNCTION__, __LINE__, #task_work_func, \
- utrace->task, utrace->task->tgid, \
- (utrace->task->comm \
- ? utrace->task->comm \
- : "UNKNOWN")); \
- }
-#else
-#define CANCEL_IF_WORK(added_field, task_work_func) \
- if (atomic_add_unless(&added_field, \
- -1, 0)) { \
- stp_task_work_cancel(utrace->task, \
- &task_work_func); \
- }
-#endif
+static void utrace_cancel_workers(struct utrace_bucket *bucket,
+ struct utrace *utrace)
+{
+ static const task_work_func_t task_workers[] = {
+ utrace_resume,
+ utrace_report_work,
+ utrace_exec_work,
+ utrace_syscall_entry_work,
+ utrace_syscall_exit_work,
+ utrace_clone_work
+ };
+ int i;
+
+ /*
+ * Cancel every task worker instance. stp_task_work_cancel() only
+ * cancels one worker at a time, so we need to run it multiple times to
+ * ensure all of the workers are really gone. We don't bother putting
+ * the references on the utrace struct because the structs will be freed
+ * by force later, after task workers can no longer run or be queued.
+ */
+ for (i = 0; i < ARRAY_SIZE(task_workers); i++)
+ while (stp_task_work_cancel(utrace->task, task_workers[i]));
+}
static void utrace_cancel_all_task_work(void)
{
@@ -603,7 +614,6 @@ static void utrace_cancel_all_task_work(void)
struct hlist_head *head;
struct hlist_node *utrace_node;
struct __stp_utrace_task_work *task_node;
- unsigned long flags;
/* Cancel any pending utrace task_work item(s). */
for (i = 0; i < TASK_UTRACE_TABLE_SIZE; i++) {
@@ -611,18 +621,11 @@ static void utrace_cancel_all_task_work(void)
rcu_read_lock();
stap_hlist_for_each_entry_rcu(utrace, utrace_node, &bucket->head, hlist) {
- CANCEL_IF_WORK(utrace->resume_work_added, utrace_resume);
- CANCEL_IF_WORK(utrace->report_work_added, utrace_report_work);
+ if (atomic_read(&utrace->refcount))
+ utrace_cancel_workers(bucket, utrace);
}
rcu_read_unlock();
}
-
- /* Cancel any pending task_work_list item(s). */
- stp_spin_lock_irqsave(&__stp_utrace_task_work_list_lock, flags);
- list_for_each_entry(task_node, &__stp_utrace_task_work_list, list) {
- stp_task_work_cancel(task_node->task, task_node->work.func);
- }
- stp_spin_unlock_irqrestore(&__stp_utrace_task_work_list_lock, flags);
}
static void utrace_shutdown(void)
@@ -656,13 +659,13 @@ static void utrace_shutdown(void)
utrace_cancel_all_task_work();
}
-static struct utrace_bucket *get_utrace_bucket(struct task_struct *task)
+static struct utrace_bucket *find_utrace_bucket(struct task_struct *task)
{
return &task_utrace_table[hash_ptr(task, TASK_UTRACE_HASH_BITS)];
}
-static struct utrace *task_utrace_struct(struct utrace_bucket *bucket,
- struct task_struct *task)
+static struct utrace *get_utrace_struct(struct utrace_bucket *bucket,
+ struct task_struct *task)
{
struct utrace *utrace, *found = NULL;
struct hlist_node *node;
@@ -670,7 +673,8 @@ static struct utrace *task_utrace_struct(struct utrace_bucket *bucket,
rcu_read_lock();
stap_hlist_for_each_entry_rcu(utrace, node, &bucket->head, hlist) {
if (utrace->task == task) {
- found = utrace;
+ if (atomic_add_unless(&utrace->refcount, 1, 0))
+ found = utrace;
break;
}
}
@@ -697,6 +701,9 @@ static struct utrace *utrace_task_alloc(struct utrace_bucket *bucket,
if (unlikely(!utrace))
return NULL;
+ /* Acquire a reference to the task struct so it remains valid */
+ get_task_struct(task);
+
spin_lock_init(&utrace->lock);
INIT_LIST_HEAD(&utrace->attached);
INIT_LIST_HEAD(&utrace->attaching);
@@ -706,6 +713,7 @@ static struct utrace *utrace_task_alloc(struct utrace_bucket *bucket,
stp_init_task_work(&utrace->report_work, &utrace_report_work);
atomic_set(&utrace->resume_work_added, 0);
atomic_set(&utrace->report_work_added, 0);
+ atomic_set(&utrace->refcount, 1);
stp_spin_lock_irqsave(&bucket->lock, flags);
hlist_add_head_rcu(&utrace->hlist, &bucket->head);
@@ -713,20 +721,6 @@ static struct utrace *utrace_task_alloc(struct utrace_bucket *bucket,
return utrace;
}
-/* macros for utrace_free(): */
-#define FREE_IF_WORK(added_field, task_work_func) \
- if (atomic_add_unless(&added_field, -1, 0)) { \
- if ((stp_task_work_cancel(utrace->task, &task_work_func) \
- == NULL) \
- && (utrace->task->flags & ~PF_EXITING) \
- && (utrace->task->exit_state == 0)) \
- printk(KERN_ERR "%s:%d * task_work_cancel() failed for %s? task %p, %d, %s, 0x%lx 0x%x\n", \
- __FUNCTION__, __LINE__, #task_work_func, \
- utrace->task, utrace->task->tgid, \
- (utrace->task->comm ? utrace->task->comm \
- : "UNKNOWN"), utrace->task->state, utrace->task->exit_state); \
- }
-
/*
* Correctly free a @utrace structure.
*
@@ -734,36 +728,13 @@ static struct utrace *utrace_task_alloc(struct utrace_bucket *bucket,
* free_task() when @task is being deallocated. But free_task() has no
* tracepoint we can easily hook.
*/
-static void utrace_free(struct utrace_bucket *bucket, struct utrace *utrace)
+static void put_utrace_struct(struct utrace_bucket *bucket,
+ struct utrace *utrace)
{
- unsigned long flags;
-
- if (unlikely(!utrace))
+ if (!utrace || atomic_dec_return(&utrace->refcount))
return;
- /* Remove this utrace from the mapping list of tasks to
- * struct utrace. */
- stp_spin_lock_irqsave(&bucket->lock, flags);
- hlist_del_rcu(&utrace->hlist);
- stp_spin_unlock_irqrestore(&bucket->lock, flags);
-
- /* Free the utrace struct. */
-#ifdef STP_TF_DEBUG
- spin_lock(&utrace->lock);
- if (unlikely(utrace->reporting)
- || unlikely(!list_empty(&utrace->attached))
- || unlikely(!list_empty(&utrace->attaching)))
- printk(KERN_ERR "%s:%d - reporting? %p, attached empty %d, attaching empty %d\n",
- __FUNCTION__, __LINE__, utrace->reporting,
- list_empty(&utrace->attached),
- list_empty(&utrace->attaching));
- spin_unlock(&utrace->lock);
-#endif
-
- FREE_IF_WORK(utrace->resume_work_added, utrace_resume);
- FREE_IF_WORK(utrace->report_work_added, utrace_report_work);
-
- kfree_rcu(utrace, rcu);
+ utrace_cleanup(bucket, utrace);
}
/*
@@ -839,7 +810,7 @@ static int utrace_add_engine(struct task_struct *target,
* utrace_flags is not zero. Since we did unlock+lock
* at least once after utrace_task_alloc() installed
* ->utrace, we have the necessary barrier which pairs
- * with rmb() in task_utrace_struct().
+ * with rmb() in get_utrace_struct().
*/
ret = -ESRCH;
/* FIXME: Hmm, no reap in the brave new world... */
@@ -912,9 +883,10 @@ static struct utrace_engine *utrace_attach_task(
struct task_struct *target, int flags,
const struct utrace_engine_ops *ops, void *data)
{
- struct utrace_bucket *bucket = get_utrace_bucket(target);
- struct utrace *utrace = task_utrace_struct(bucket, target);
+ struct utrace_bucket *bucket = find_utrace_bucket(target);
+ struct utrace *utrace = get_utrace_struct(bucket, target);
struct utrace_engine *engine;
+ bool utrace_found = utrace;
int ret;
#ifdef STP_TF_DEBUG
@@ -923,6 +895,7 @@ static struct utrace_engine *utrace_attach_task(
#endif
if (!(flags & UTRACE_ATTACH_CREATE)) {
+ /* Don't need to put utrace struct if it's NULL */
if (unlikely(!utrace))
return ERR_PTR(-ENOENT);
spin_lock(&utrace->lock);
@@ -930,27 +903,35 @@ static struct utrace_engine *utrace_attach_task(
if (engine)
utrace_engine_get(engine);
spin_unlock(&utrace->lock);
+ put_utrace_struct(bucket, utrace);
return engine ?: ERR_PTR(-ENOENT);
}
- if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops))
+ if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops)) {
+ put_utrace_struct(bucket, utrace);
return ERR_PTR(-EINVAL);
+ }
- if (unlikely(target->flags & PF_KTHREAD))
+ if (unlikely(target->flags & PF_KTHREAD)) {
/*
* Silly kernel, utrace is for users!
*/
+ put_utrace_struct(bucket, utrace);
return ERR_PTR(-EPERM);
+ }
if (!utrace) {
utrace = utrace_task_alloc(bucket, target);
+ /* Don't need to put utrace struct if it's NULL */
if (unlikely(!utrace))
return ERR_PTR(-ENOMEM);
}
engine = _stp_kmalloc(sizeof(*engine));
- if (unlikely(!engine))
+ if (unlikely(!engine)) {
+ put_utrace_struct(bucket, utrace);
return ERR_PTR(-ENOMEM);
+ }
/*
* Initialize the new engine structure. It starts out with one ref
@@ -969,6 +950,14 @@ static struct utrace_engine *utrace_attach_task(
engine = ERR_PTR(ret);
}
+ /*
+ * Don't put the utrace struct if it was just made and successfully
+ * attached to, otherwise it'll disappear. We only put the new utrace
+ * struct if the engine couldn't be attached. If the utrace struct was
+ * acquired via get_utrace_struct() then we must put our reference.
+ */
+ if (ret || utrace_found)
+ put_utrace_struct(bucket, utrace);
return engine;
}
@@ -1014,13 +1003,11 @@ static const struct utrace_engine_ops utrace_detached_ops = {
* utrace_report_death
* utrace_release_task
*/
-static struct utrace *get_utrace_lock(struct task_struct *target,
- struct utrace_engine *engine,
- bool attached)
+static int get_utrace_lock(struct utrace *utrace, struct utrace_engine *engine,
+ bool attached)
__acquires(utrace->lock)
{
- struct utrace_bucket *bucket;
- struct utrace *utrace;
+ int ret = 0;
/*
* The ops pointer is NULL when the engine is fully detached.
@@ -1029,15 +1016,10 @@ static struct utrace *get_utrace_lock(struct task_struct *target,
* since the target might be in the middle of an old callback.
*/
if (unlikely(!engine->ops))
- return ERR_PTR(-ESRCH);
+ return -ESRCH;
if (unlikely(engine->ops == &utrace_detached_ops))
- return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS);
-
- bucket = get_utrace_bucket(target);
- utrace = task_utrace_struct(bucket, target);
- if (unlikely(!utrace))
- return ERR_PTR(-ESRCH);
+ return attached ? -ESRCH : -ERESTARTSYS;
spin_lock(&utrace->lock);
if (unlikely(utrace->reap) || unlikely(!engine->ops) ||
@@ -1047,12 +1029,13 @@ static struct utrace *get_utrace_lock(struct task_struct *target,
* it had been reaped or detached already.
*/
spin_unlock(&utrace->lock);
- utrace = ERR_PTR(-ESRCH);
if (!attached && engine->ops == &utrace_detached_ops)
- utrace = ERR_PTR(-ERESTARTSYS);
+ ret = -ERESTARTSYS;
+ else
+ ret = -ESRCH;
}
- return utrace;
+ return ret;
}
/*
@@ -1139,9 +1122,10 @@ static int utrace_set_events(struct task_struct *target,
struct utrace_engine *engine,
unsigned long events)
{
+ struct utrace_bucket *bucket;
struct utrace *utrace;
unsigned long old_flags, old_utrace_flags;
- int ret = -EALREADY;
+ int ret;
/*
* We just ignore the internal bit, so callers can use
@@ -1149,9 +1133,14 @@ static int utrace_set_events(struct task_struct *target,
*/
events &= ~ENGINE_STOP;
- utrace = get_utrace_lock(target, engine, true);
- if (unlikely(IS_ERR(utrace)))
- return PTR_ERR(utrace);
+ bucket = find_utrace_bucket(target);
+ utrace = get_utrace_struct(bucket, target);
+ if (!utrace)
+ return -ESRCH;
+
+ ret = get_utrace_lock(utrace, engine, true);
+ if (ret)
+ goto put_utrace;
old_utrace_flags = utrace->utrace_flags;
old_flags = engine->flags & ~ENGINE_STOP;
@@ -1164,8 +1153,10 @@ static int utrace_set_events(struct task_struct *target,
(((events & ~old_flags) & _UTRACE_DEATH_EVENTS) ||
(utrace->death &&
((old_flags & ~events) & _UTRACE_DEATH_EVENTS)) ||
- (utrace->reap && ((old_flags & ~events) & UTRACE_EVENT(REAP)))))
+ (utrace->reap && ((old_flags & ~events) & UTRACE_EVENT(REAP))))) {
+ ret = -EALREADY;
goto unlock;
+ }
/*
* When setting these flags, it's essential that we really
@@ -1186,6 +1177,7 @@ static int utrace_set_events(struct task_struct *target,
//read_lock(&tasklist_lock);
if (unlikely(target->exit_state)) {
//read_unlock(&tasklist_lock);
+ ret = -EALREADY;
goto unlock;
}
utrace->utrace_flags |= events;
@@ -1212,7 +1204,8 @@ static int utrace_set_events(struct task_struct *target,
}
unlock:
spin_unlock(&utrace->lock);
-
+put_utrace:
+ put_utrace_struct(bucket, utrace);
return ret;
}
@@ -1348,10 +1341,14 @@ static void utrace_finish_stop(void)
* sure we do nothing until the tracer drops utrace->lock.
*/
if (unlikely(__fatal_signal_pending(current))) {
- struct utrace_bucket *bucket = get_utrace_bucket(current);
- struct utrace *utrace = task_utrace_struct(bucket, current);
- spin_lock(&utrace->lock);
- spin_unlock(&utrace->lock);
+ struct utrace_bucket *bucket = find_utrace_bucket(current);
+ struct utrace *utrace = get_utrace_struct(bucket, current);
+
+ if (utrace) {
+ spin_lock(&utrace->lock);
+ spin_unlock(&utrace->lock);
+ put_utrace_struct(bucket, utrace);
+ }
}
}
@@ -1640,6 +1637,7 @@ static int utrace_control(struct task_struct *target,
struct utrace_engine *engine,
enum utrace_resume_action action)
{
+ struct utrace_bucket *bucket;
struct utrace *utrace;
bool reset;
int ret;
@@ -1663,9 +1661,14 @@ static int utrace_control(struct task_struct *target,
return -EINVAL;
}
- utrace = get_utrace_lock(target, engine, true);
- if (unlikely(IS_ERR(utrace)))
- return PTR_ERR(utrace);
+ bucket = find_utrace_bucket(target);
+ utrace = get_utrace_struct(bucket, target);
+ if (!utrace)
+ return -ESRCH;
+
+ ret = get_utrace_lock(utrace, engine, true);
+ if (ret)
+ goto put_utrace;
reset = task_is_traced(target);
ret = 0;
@@ -1680,7 +1683,7 @@ static int utrace_control(struct task_struct *target,
ret = utrace_control_dead(target, utrace, action);
if (ret) {
spin_unlock(&utrace->lock);
- return ret;
+ goto put_utrace;
}
reset = true;
}
@@ -1779,6 +1782,8 @@ static int utrace_control(struct task_struct *target,
else
spin_unlock(&utrace->lock);
+put_utrace:
+ put_utrace_struct(bucket, utrace);
return ret;
}
@@ -1806,8 +1811,9 @@ static int utrace_control(struct task_struct *target,
static int utrace_barrier(struct task_struct *target,
struct utrace_engine *engine)
{
+ struct utrace_bucket *bucket;
struct utrace *utrace;
- int ret = -ERESTARTSYS;
+ int ret;
if (unlikely(target == current))
return 0;
@@ -1815,10 +1821,15 @@ static int utrace_barrier(struct task_struct *target,
/* If we get here, we might call
* schedule_timeout_interruptible(), which sleeps. */
might_sleep();
+
+ bucket = find_utrace_bucket(target);
+ utrace = get_utrace_struct(bucket, target);
+ if (!utrace)
+ return -ESRCH;
+
do {
- utrace = get_utrace_lock(target, engine, false);
- if (unlikely(IS_ERR(utrace))) {
- ret = PTR_ERR(utrace);
+ ret = get_utrace_lock(utrace, engine, false);
+ if (ret) {
if (ret != -ERESTARTSYS)
break;
} else {
@@ -1836,6 +1847,8 @@ static int utrace_barrier(struct task_struct *target,
*/
if (utrace->reporting != engine)
ret = 0;
+ else
+ ret = -ERESTARTSYS;
spin_unlock(&utrace->lock);
if (!ret)
break;
@@ -1843,6 +1856,7 @@ static int utrace_barrier(struct task_struct *target,
schedule_timeout_interruptible(1);
} while (!signal_pending(current));
+ put_utrace_struct(bucket, utrace);
return ret;
}
@@ -2140,11 +2154,14 @@ static void utrace_report_exec(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
- if (!utrace || !(utrace->utrace_flags & UTRACE_EVENT(EXEC)))
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
return;
+ if (!(utrace->utrace_flags & UTRACE_EVENT(EXEC)))
+ goto put_utrace;
+
#if 0
if (!in_atomic() && !irqs_disabled())
printk(KERN_ERR
@@ -2156,16 +2173,20 @@ static void utrace_report_exec(void *cb_data __attribute__ ((unused)),
work = __stp_utrace_alloc_task_work(utrace, (void *)NULL);
if (work == NULL) {
_stp_error("Unable to allocate space for task_work");
- return;
+ goto put_utrace;
}
stp_init_task_work(work, &utrace_exec_work);
rc = stp_task_work_add(task, work);
+ /* Pass our utrace struct reference onto the worker */
+ if (!rc)
+ return;
// stp_task_work_add() returns -ESRCH if the task has already
// passed exit_task_work(). Just ignore this error.
- if (rc != 0 && rc != -ESRCH) {
+ if (rc != -ESRCH)
printk(KERN_ERR "%s:%d - stp_task_work_add() returned %d\n",
__FUNCTION__, __LINE__, rc);
- }
+put_utrace:
+ put_utrace_struct(bucket, utrace);
#else
// This is the original version.
struct utrace_bucket *bucket;
@@ -2174,15 +2195,19 @@ static void utrace_report_exec(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
- if (utrace && utrace->utrace_flags & UTRACE_EVENT(EXEC)) {
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
+ return;
+
+ if (utrace->utrace_flags & UTRACE_EVENT(EXEC)) {
INIT_REPORT(report);
/* FIXME: Hmm, can we get regs another way? */
REPORT(task, utrace, &report, UTRACE_EVENT(EXEC),
report_exec, NULL, NULL, NULL /* regs */);
}
+ put_utrace_struct(bucket, utrace);
#endif
}
@@ -2192,6 +2217,7 @@ static void utrace_exec_work(struct task_work *work)
container_of(work, struct __stp_utrace_task_work, work);
struct utrace *utrace = utrace_work->utrace;
struct task_struct *task = current;
+ struct utrace_bucket *bucket = find_utrace_bucket(task);
INIT_REPORT(report);
@@ -2202,6 +2228,8 @@ static void utrace_exec_work(struct task_work *work)
report_exec, NULL, NULL, NULL /* regs */);
__stp_utrace_free_task_work(work);
+ put_utrace_struct(bucket, utrace);
+
/* Remember that this task_work_func is finished. */
stp_task_work_func_done();
}
@@ -2270,14 +2298,16 @@ static void utrace_report_syscall_entry(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
- /* FIXME: Is this 100% correct? */
- if (!utrace
- || !(utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_ENTRY)|ENGINE_STOP)))
+ if (!utrace)
return;
+ /* FIXME: Is this 100% correct? */
+ if (!(utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_ENTRY)|ENGINE_STOP)))
+ goto put_utrace;;
+
#if 0
if (!in_atomic() && !irqs_disabled())
printk(KERN_ERR
@@ -2289,17 +2319,21 @@ static void utrace_report_syscall_entry(void *cb_data __attribute__ ((unused)),
work = __stp_utrace_alloc_task_work(utrace, NULL);
if (work == NULL) {
_stp_error("Unable to allocate space for task_work");
- return;
+ goto put_utrace;
}
__stp_utrace_save_regs(work, regs);
stp_init_task_work(work, &utrace_syscall_entry_work);
rc = stp_task_work_add(task, work);
+ /* Pass our utrace struct reference onto the worker */
+ if (!rc)
+ return;
// stp_task_work_add() returns -ESRCH if the task has already
// passed exit_task_work(). Just ignore this error.
- if (rc != 0 && rc != -ESRCH) {
+ if (rc != -ESRCH)
printk(KERN_ERR "%s:%d - stp_task_work_add() returned %d\n",
__FUNCTION__, __LINE__, rc);
- }
+put_utrace:
+ put_utrace_struct(bucket, utrace);
#else
// This is the original version.
struct task_struct *task = current;
@@ -2309,12 +2343,13 @@ static void utrace_report_syscall_entry(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
+ return;
/* FIXME: Is this 100% correct? */
- if (utrace
- && utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_ENTRY)|ENGINE_STOP)) {
+ if (utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_ENTRY)|ENGINE_STOP)) {
INIT_REPORT(report);
@@ -2323,6 +2358,7 @@ static void utrace_report_syscall_entry(void *cb_data __attribute__ ((unused)),
REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_ENTRY),
report_syscall_entry, regs);
}
+ put_utrace_struct(bucket, utrace);
#if 0
INIT_REPORT(report);
@@ -2344,6 +2380,7 @@ static void utrace_syscall_entry_work(struct task_work *work)
container_of(work, struct __stp_utrace_task_work, work);
struct utrace *utrace = utrace_work->utrace;
struct task_struct *task = current;
+ struct utrace_bucket *bucket = find_utrace_bucket(task);
struct pt_regs *regs = &utrace_work->regs;
INIT_REPORT(report);
@@ -2356,6 +2393,8 @@ static void utrace_syscall_entry_work(struct task_work *work)
report_syscall_entry, regs);
__stp_utrace_free_task_work(work);
+ put_utrace_struct(bucket, utrace);
+
/* Remember that this task_work_func is finished. */
stp_task_work_func_done();
}
@@ -2377,13 +2416,14 @@ static void utrace_report_syscall_exit(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
+ return;
/* FIXME: Is this 100% correct? */
- if (!utrace
- || !(utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_EXIT)|ENGINE_STOP)))
- return;
+ if (!(utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_EXIT)|ENGINE_STOP)))
+ goto put_utrace;
#if 0
if (!in_atomic() && !irqs_disabled())
@@ -2396,17 +2436,21 @@ static void utrace_report_syscall_exit(void *cb_data __attribute__ ((unused)),
work = __stp_utrace_alloc_task_work(utrace, NULL);
if (work == NULL) {
_stp_error("Unable to allocate space for task_work");
- return;
+ goto put_utrace;
}
__stp_utrace_save_regs(work, regs);
stp_init_task_work(work, &utrace_syscall_exit_work);
rc = stp_task_work_add(task, work);
+ /* Pass our utrace struct reference onto the worker */
+ if (!rc)
+ return;
// stp_task_work_add() returns -ESRCH if the task has already
// passed exit_task_work(). Just ignore this error.
- if (rc != 0 && rc != -ESRCH) {
+ if (rc != -ESRCH)
printk(KERN_ERR "%s:%d - stp_task_work_add() returned %d\n",
__FUNCTION__, __LINE__, rc);
- }
+put_utrace:
+ put_utrace_struct(bucket, utrace);
#else
// This is the original version.
struct task_struct *task = current;
@@ -2416,12 +2460,13 @@ static void utrace_report_syscall_exit(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
+ return;
/* FIXME: Is this 100% correct? */
- if (utrace
- && utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_EXIT)|ENGINE_STOP)) {
+ if (utrace->utrace_flags & (UTRACE_EVENT(SYSCALL_EXIT)|ENGINE_STOP)) {
INIT_REPORT(report);
#ifdef STP_TF_DEBUG
@@ -2432,6 +2477,7 @@ static void utrace_report_syscall_exit(void *cb_data __attribute__ ((unused)),
REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT),
report_syscall_exit, regs);
}
+ put_utrace_struct(bucket, utrace);
#endif
}
@@ -2441,6 +2487,7 @@ static void utrace_syscall_exit_work(struct task_work *work)
container_of(work, struct __stp_utrace_task_work, work);
struct utrace *utrace = utrace_work->utrace;
struct task_struct *task = current;
+ struct utrace_bucket *bucket = find_utrace_bucket(task);
struct pt_regs *regs = &utrace_work->regs;
INIT_REPORT(report);
@@ -2462,6 +2509,8 @@ static void utrace_syscall_exit_work(struct task_work *work)
REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT),
report_syscall_exit, regs);
+ put_utrace_struct(bucket, utrace);
+
/* Remember that this task_work_func is finished. */
stp_task_work_func_done();
}
@@ -2489,17 +2538,18 @@ static void utrace_report_clone(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
+ return;
#ifdef STP_TF_DEBUG
printk(KERN_ERR "%s:%d - parent %p, child %p, current %p\n",
__FUNCTION__, __LINE__, task, child, current);
#endif
- if (!utrace
- || !(utrace->utrace_flags & UTRACE_EVENT(CLONE)))
- return;
+ if (!(utrace->utrace_flags & UTRACE_EVENT(CLONE)))
+ goto put_utrace;
// TODO: Need to double-check the lifetime of struct child.
@@ -2507,16 +2557,20 @@ static void utrace_report_clone(void *cb_data __attribute__ ((unused)),
work = __stp_utrace_alloc_task_work(utrace, (void *)child);
if (work == NULL) {
_stp_error("Unable to allocate space for task_work");
- return;
+ goto put_utrace;
}
stp_init_task_work(work, &utrace_clone_work);
rc = stp_task_work_add(task, work);
+ /* Pass our utrace struct reference onto the worker */
+ if (!rc)
+ return;
// stp_task_work_add() returns -ESRCH if the task has already
// passed exit_task_work(). Just ignore this error.
- if (rc != 0 && rc != -ESRCH) {
+ if (rc != -ESRCH)
printk(KERN_ERR "%s:%d - stp_task_work_add() returned %d\n",
__FUNCTION__, __LINE__, rc);
- }
+put_utrace:
+ put_utrace_struct(bucket, utrace);
#else
// This is the original version.
struct utrace_bucket *bucket;
@@ -2525,15 +2579,17 @@ static void utrace_report_clone(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
+ return;
#ifdef STP_TF_DEBUG
printk(KERN_ERR "%s:%d - parent %p, child %p, current %p\n",
__FUNCTION__, __LINE__, task, child, current);
#endif
- if (utrace && utrace->utrace_flags & UTRACE_EVENT(CLONE)) {
+ if (utrace->utrace_flags & UTRACE_EVENT(CLONE)) {
unsigned long clone_flags = 0;
INIT_REPORT(report);
@@ -2595,6 +2651,7 @@ static void utrace_report_clone(void *cb_data __attribute__ ((unused)),
}
#endif
}
+ put_utrace_struct(bucket, utrace);
#endif
}
@@ -2604,6 +2661,7 @@ static void utrace_clone_work(struct task_work *work)
container_of(work, struct __stp_utrace_task_work, work);
struct utrace *utrace = utrace_work->utrace;
struct task_struct *task = current;
+ struct utrace_bucket *bucket = find_utrace_bucket(task);
struct task_struct *child = (struct task_struct *)utrace_work->data;
unsigned long clone_flags = 0;
@@ -2670,6 +2728,8 @@ static void utrace_clone_work(struct task_work *work)
}
#endif
+ put_utrace_struct(bucket, utrace);
+
/* Remember that this task_work_func is finished. */
stp_task_work_func_done();
}
@@ -2686,8 +2746,8 @@ static void utrace_clone_work(struct task_work *work)
*/
static void utrace_finish_vfork(struct task_struct *task)
{
- struct utrace_bucket *bucket = get_utrace_bucket(task);
- struct utrace *utrace = task_utrace_struct(bucket, task);
+ struct utrace_bucket *bucket = find_utrace_bucket(task);
+ struct utrace *utrace = get_utrace_struct(bucket, task);
if (utrace->vfork_stop) {
spin_lock(&utrace->lock);
@@ -2713,14 +2773,16 @@ static void utrace_report_death(void *cb_data __attribute__ ((unused)),
if (atomic_read(&utrace_state) != __UTRACE_REGISTERED)
return;
- bucket = get_utrace_bucket(task);
- utrace = task_utrace_struct(bucket, task);
+ bucket = find_utrace_bucket(task);
+ utrace = get_utrace_struct(bucket, task);
+ if (!utrace)
+ return;
#ifdef STP_TF_DEBUG
printk(KERN_ERR "%s:%d - task %p, utrace %p, flags %lx\n", __FUNCTION__, __LINE__, task, utrace, utrace ? utrace->utrace_flags : 0);
#endif
- if (!utrace || !(utrace->utrace_flags & UTRACE_EVENT(DEATH)))
- return;
+ if (!(utrace->utrace_flags & UTRACE_EVENT(DEATH)))
+ goto put_utrace;
/* This code is called from the 'sched_process_exit'
* tracepoint, which really corresponds more to UTRACE_EXIT
@@ -2752,19 +2814,22 @@ static void utrace_report_death(void *cb_data __attribute__ ((unused)),
__FUNCTION__, __LINE__);
#endif
rc = stp_task_work_add(task, &utrace->report_work);
- if (rc != 0) {
- atomic_set(&utrace->report_work_added, 0);
- /* stp_task_work_add() returns -ESRCH
- * if the task has already passed
- * exit_task_work(). Just ignore this
- * error. */
- if (rc != -ESRCH) {
- printk(KERN_ERR
- "%s:%d - task_work_add() returned %d\n",
- __FUNCTION__, __LINE__, rc);
- }
+ /* Pass our utrace struct reference onto the worker */
+ if (!rc)
+ return;
+ atomic_set(&utrace->report_work_added, 0);
+ /* stp_task_work_add() returns -ESRCH
+ * if the task has already passed
+ * exit_task_work(). Just ignore this
+ * error. */
+ if (rc != -ESRCH) {
+ printk(KERN_ERR
+ "%s:%d - task_work_add() returned %d\n",
+ __FUNCTION__, __LINE__, rc);
}
}
+put_utrace:
+ put_utrace_struct(bucket, utrace);
}
/*
@@ -2803,13 +2868,14 @@ static void finish_resume_report(struct task_struct *task,
static void utrace_resume(struct task_work *work)
{
/*
- * We could also do 'task_utrace_struct()' here to find the
+ * We could also do 'get_utrace_struct()' here to find the
* task's 'struct utrace', but 'container_of()' should be
- * instantaneous (where 'task_utrace_struct()' has to do a
+ * instantaneous (where 'get_utrace_struct()' has to do a
* hash lookup).
*/
struct utrace *utrace = container_of(work, struct utrace, resume_work);
struct task_struct *task = current;
+ struct utrace_bucket *bucket = find_utrace_bucket(task);
INIT_REPORT(report);
struct utrace_engine *engine;
@@ -2817,11 +2883,8 @@ static void utrace_resume(struct task_work *work)
atomic_set(&utrace->resume_work_added, 0);
/* Make sure the task isn't exiting. */
- if (task->flags & PF_EXITING) {
- /* Remember that this task_work_func is finished. */
- stp_task_work_func_done();
- return;
- }
+ if (task->flags & PF_EXITING)
+ goto exit;
/*
* Some machines get here with interrupts disabled. The same arch
@@ -2844,9 +2907,7 @@ static void utrace_resume(struct task_work *work)
* purposes as well as calling us.)
*/
- /* Remember that this task_work_func is finished. */
- stp_task_work_func_done();
- return;
+ goto exit;
case UTRACE_INTERRUPT:
/*
* Note that UTRACE_INTERRUPT reporting was handled by
@@ -2883,6 +2944,9 @@ static void utrace_resume(struct task_work *work)
*/
finish_resume_report(task, utrace, &report);
+exit:
+ put_utrace_struct(bucket, utrace);
+
/* Remember that this task_work_func is finished. */
stp_task_work_func_done();
}
@@ -2891,14 +2955,14 @@ static void utrace_resume(struct task_work *work)
static void utrace_report_work(struct task_work *work)
{
/*
- * We could also do 'task_utrace_struct()' here to find the
+ * We could also do 'get_utrace_struct()' here to find the
* task's 'struct utrace', but 'container_of()' should be
- * instantaneous (where 'task_utrace_struct()' has to do a
+ * instantaneous (where 'get_utrace_struct()' has to do a
* hash lookup).
*/
struct utrace *utrace = container_of(work, struct utrace, report_work);
struct task_struct *task = current;
- struct utrace_bucket *bucket = get_utrace_bucket(task);
+ struct utrace_bucket *bucket = find_utrace_bucket(task);
INIT_REPORT(report);
struct utrace_engine *engine;
unsigned long clone_flags;
@@ -2922,7 +2986,10 @@ static void utrace_report_work(struct task_work *work)
-1/*signal*/);
utrace_maybe_reap(task, utrace, false);
- utrace_free(bucket, utrace);
+
+ /* Put two references on the utrace struct to free it */
+ put_utrace_struct(bucket, utrace);
+ put_utrace_struct(bucket, utrace);
/* Remember that this task_work_func is finished. */
stp_task_work_func_done();
--
2.30.0
--- systemtap-before.sum 2021-02-05 16:41:57.440992820 -0800
+++ systemtap-after.sum 2021-02-05 18:15:41.238437212 -0800
@@ -1,4 +1,4 @@
-Test Run By root on Fri Feb 5 16:00:09 2021
+Test Run By root on Fri Feb 5 17:35:04 2021
Native configuration is x86_64-unknown-linux-gnu
=== systemtap tests ===
@@ -45,7 +45,10 @@
PASS: abort: TEST 5: abort() in the middle of a probe handler body (--compatible 3.3): stdout: string is ""
PASS: abort: TEST 5: abort() in the middle of a probe handler body (--compatible 3.3): exit code: string should NOT be "0"
PASS: abort: TEST 5: abort() in the middle of a probe handler body (--compatible 3.3): stderr: matches regex "^semantic error: unresolved function.*\(similar: [^\n]*?\): identifier 'abort' at [^\n]*?\.stp:3:5\n"
-PASS: abort: TEST 6: abort() in timer.profile (using globals): stdout: string is "fire 3!\nfire 2!\nfire 1!\n"
+FAIL: abort: TEST 6: abort() in timer.profile (using globals): stdout: string should be "fire 3!\nfire 2!\nfire 1!\n", but got "fire 1!
+fire 3!
+fire 2!
+"
PASS: abort: TEST 6: abort() in timer.profile (using globals): exit code: string is "0"
PASS: abort: TEST 7: abort() in timer.profile (more concurrency and no globals): stdout: string is ""
PASS: abort: TEST 7: abort() in timer.profile (more concurrency and no globals): stderr: string is ""
@@ -63,7 +66,7 @@
FAIL: additional_scripts (-E BAD_SCRIPT listing probes)
PASS: additional_scripts (-e and -E )
PASS: additional_scripts (file and -E )
-FAIL: additional_scripts (multiple -E)
+PASS: additional_scripts (multiple -E )
Running /home/sultan/systemtap/testsuite/systemtap.base/addr_op.exp ...
PASS: addr_op: TEST 1: 2 excessive parens after unary '&' - with components (kernel): stdout: string is "1\n"
PASS: addr_op: TEST 1: 2 excessive parens after unary '&' - with components (kernel): exit code: string is "0"
@@ -206,7 +209,7 @@
FAIL: at_var_cu
Running /home/sultan/systemtap/testsuite/systemtap.base/at_var.exp ...
PASS: at_var
-FAIL: at_var (non-optimized)
+PASS: at_var (non-optimized)
FAIL: at_var
PASS: at_var (non-optimized)
Running /home/sultan/systemtap/testsuite/systemtap.base/at_var_func.exp ...
@@ -244,7 +247,7 @@
PASS: auto_path2
PASS: auto_path3
Running /home/sultan/systemtap/testsuite/systemtap.base/backtrace.exp ...
-PASS: backtrace (3 37)
+PASS: backtrace (3 41)
PASS: backtrace-unwindsyms (3 35)
PASS: self-unwind-ensure-exact (0)
Running /home/sultan/systemtap/testsuite/systemtap.base/bad-code.exp ...
@@ -301,7 +304,7 @@
Running /home/sultan/systemtap/testsuite/systemtap.base/bz1074541.exp ...
PASS: ./bz1074541
Running /home/sultan/systemtap/testsuite/systemtap.base/bz1126645.exp ...
-FAIL: bz1126645 -p5 (547)
+FAIL: bz1126645 -p5 (44)
Running /home/sultan/systemtap/testsuite/systemtap.base/bz1214176.exp ...
PASS: stap -p4 -e { probe nfs.proc.read_done { println(server_ip) } }
PASS: stap -p4 -e { probe nfs.proc.read_setup { println(count) } }
@@ -399,7 +402,7 @@
PASS: cast-user compile
FAIL: cast-user
Running /home/sultan/systemtap/testsuite/systemtap.base/cmdline.exp ...
-FAIL: cmdline
+PASS: cmdline
Running /home/sultan/systemtap/testsuite/systemtap.base/cmd_parse.exp ...
PASS: cmd_parse1
PASS: cmd_parse2
@@ -634,7 +637,7 @@
FAIL: enum compiling enum.c
Running /home/sultan/systemtap/testsuite/systemtap.base/environment_sanity.exp ...
Host: Linux centos7-bb 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
-Snapshot: version 4.5/0.177, commit release-4.4-89-g1ef2edcd3aa1
+Snapshot: version 4.5/0.177, commit release-4.4-90-g8d16bd1cc2a8
GCC: 4.8.5 [gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)]
Distro: CentOS Linux release 7.8.2003 (Core)
SElinux: Enforcing
@@ -2786,10 +2789,10 @@
Running /home/sultan/systemtap/testsuite/systemtap.base/optim.exp ...
PASS: optim
Running /home/sultan/systemtap/testsuite/systemtap.base/optim_stats.exp ...
-PASS: TEST1 (5, 14)
-PASS: TEST2 (20, 86)
-PASS: TEST3 (5, 7)
-PASS: TEST4 (20, 66)
+PASS: TEST1 (5, 11)
+PASS: TEST2 (20, 85)
+PASS: TEST3 (5, 6)
+PASS: TEST4 (20, 67)
Running /home/sultan/systemtap/testsuite/systemtap.base/optim_voidstmt.exp ...
PASS: optim_voidstmt startup
PASS: optim_voidstmt load generation
@@ -2823,7 +2826,7 @@
FAIL: perf process (0 - 0)
PASS: perf counter
FAIL: perf global (0 - 0)
-UNRESOLVED: counter order 800000 7000000
+UNRESOLVED: counter order 8000000 800000
Running /home/sultan/systemtap/testsuite/systemtap.base/plt.exp ...
PASS: plt
PASS: plt library
@@ -2914,7 +2917,6 @@
PASS: probefunc:kernel.function("scheduler_tick") startup
PASS: probefunc:kernel.function("scheduler_tick") load generation
PASS: probefunc:kernel.function("scheduler_tick") shutdown and output
-FAIL: probefunc:kernel.function("scheduler_tick") unexpected output (after passing output)
PASS: probefunc:kernel.function("context_switch").inline startup
PASS: probefunc:kernel.function("context_switch").inline load generation
PASS: probefunc:kernel.function("context_switch").inline shutdown and output
@@ -2952,18 +2954,14 @@
PASS: process_resume-getpid: process resumed properly
PASS: process_resume-end startup
PASS: process_resume-end load generation
-FAIL: process_resume-end unexpected output
+PASS: process_resume-end shutdown and output
PASS: process_resume-end: process resumed properly
Running /home/sultan/systemtap/testsuite/systemtap.base/proc_exec.exp ...
-PASS: PROC_EXEC_01 startup
-PASS: PROC_EXEC_01 load generation
-PASS: PROC_EXEC_01 shutdown and output
+FAIL: PROC_EXEC_01 startup (timeout)
PASS: PROC_EXEC_02 startup
PASS: PROC_EXEC_02 load generation
-PASS: PROC_EXEC_02 shutdown and output
-PASS: PROC_EXEC_03 startup
-PASS: PROC_EXEC_03 load generation
-PASS: PROC_EXEC_03 shutdown and output
+FAIL: PROC_EXEC_02 unexpected output
+FAIL: PROC_EXEC_03 startup (timeout)
Running /home/sultan/systemtap/testsuite/systemtap.base/procfs_bpf.exp ...
FAIL: PROCFS_BPF startup (eof)
Running /home/sultan/systemtap/testsuite/systemtap.base/procfs.exp ...
@@ -3315,7 +3313,7 @@
PASS: sdt_buildid compiling
PASS: sdt_buildid compiling -shared
UNTESTED: sdt_buildid debuginfod
-PASS: sdt_buildid non-buildid both
+FAIL: sdt_buildid non-buildid both
PASS: sdt_buildid non-buildid exe
PASS: sdt_buildid non-buildid solib
Running /home/sultan/systemtap/testsuite/systemtap.base/sdt_casm.exp ...
@@ -3795,7 +3793,7 @@
PASS: tracepoints - kernel.trace("bla:")
PASS: tracepoints - kernel.trace("sched:")
PASS: systemtap.base/tracepoints.stp -w
-FAIL: systemtap.base/tracepoints2.stp
+PASS: systemtap.base/tracepoints2.stp
Running /home/sultan/systemtap/testsuite/systemtap.base/tracepoints_list.exp ...
UNTESTED: tracepoints_list (no perf)
Running /home/sultan/systemtap/testsuite/systemtap.base/tracescripts.exp ...
@@ -3880,7 +3878,7 @@
Running /home/sultan/systemtap/testsuite/systemtap.base/utrace_p5.exp ...
PASS: UTRACE_P5_01 startup
PASS: UTRACE_P5_01 load generation
-FAIL: UTRACE_P5_01 unexpected output
+PASS: UTRACE_P5_01 shutdown and output
PASS: UTRACE_P5_01_cmd startup
PASS: UTRACE_P5_01_cmd load generation
PASS: UTRACE_P5_01_cmd shutdown and output
@@ -3890,21 +3888,19 @@
PASS: UTRACE_P5_02_cmd startup
PASS: UTRACE_P5_02_cmd load generation
PASS: UTRACE_P5_02_cmd shutdown and output
-PASS: UTRACE_P5_03 startup
-PASS: UTRACE_P5_03 load generation
-FAIL: UTRACE_P5_03 unexpected output
+FAIL: UTRACE_P5_03 startup (timeout)
PASS: UTRACE_P5_04 startup
PASS: UTRACE_P5_04 load generation
-FAIL: UTRACE_P5_04 unexpected output
+PASS: UTRACE_P5_04 shutdown and output
PASS: UTRACE_P5_05 startup
PASS: UTRACE_P5_05 load generation
-PASS: UTRACE_P5_05 shutdown and output
+FAIL: UTRACE_P5_05 unexpected output
PASS: UTRACE_P5_05_cmd startup
PASS: UTRACE_P5_05_cmd load generation
PASS: UTRACE_P5_05_cmd shutdown and output
PASS: UTRACE_P5_06 startup
PASS: UTRACE_P5_06 load generation
-FAIL: UTRACE_P5_06 unexpected output
+PASS: UTRACE_P5_06 shutdown and output
PASS: UTRACE_P5_06_cmd startup
PASS: UTRACE_P5_06_cmd load generation
PASS: UTRACE_P5_06_cmd shutdown and output
@@ -4144,9 +4140,7 @@
PASS: while.stp
Running /home/sultan/systemtap/testsuite/systemtap.clone/dtrace_clone.exp ...
PASS: dtrace_clone1 - build success
-PASS: dtrace_clone2 startup
-PASS: dtrace_clone2 load generation
-PASS: dtrace_clone2 shutdown and output
+FAIL: dtrace_clone2 startup (timeout)
PASS: dtrace_clone3 - build success
PASS: dtrace_clone4 startup
PASS: dtrace_clone4 load generation
@@ -4157,14 +4151,10 @@
PASS: dtrace_fork_exec2 load generation
PASS: dtrace_fork_exec2 shutdown and output
PASS: dtrace_fork_exec3 - build success
-PASS: dtrace_fork_exec4 startup
-PASS: dtrace_fork_exec4 load generation
-PASS: dtrace_fork_exec4 shutdown and output
+FAIL: dtrace_fork_exec4 startup (timeout)
Running /home/sultan/systemtap/testsuite/systemtap.clone/dtrace_vfork_exec.exp ...
PASS: dtrace_vfork_exec1 - build success
-PASS: dtrace_vfork_exec2 startup
-PASS: dtrace_vfork_exec2 load generation
-PASS: dtrace_vfork_exec2 shutdown and output
+FAIL: dtrace_vfork_exec2 startup (timeout)
PASS: dtrace_vfork_exec3 - build success
PASS: dtrace_vfork_exec4 startup
PASS: dtrace_vfork_exec4 load generation
@@ -4176,10 +4166,10 @@
PASS: main_quiesce shutdown and output
Running /home/sultan/systemtap/testsuite/systemtap.clone/probe_by_pid.exp ...
PASS: probe_by_pid(utrace) - build success
-PASS: probe_by_pid(utrace) startup
-PASS: probe_by_pid(utrace) load generation
-PASS: probe_by_pid(utrace) shutdown and output
-FAIL: probe_by_pid(function) startup (eof)
+FAIL: probe_by_pid(utrace) startup (eof)
+PASS: probe_by_pid(function) startup
+PASS: probe_by_pid(function) load generation
+FAIL: probe_by_pid(function) unexpected output
Running /home/sultan/systemtap/testsuite/systemtap.context/context.exp ...
PASS: backtrace of begin probe
FAIL: backtrace of yyy_func2 (0)
@@ -4217,9 +4207,7 @@
PASS: symline ()
PASS: symfileline in pp ()
Running /home/sultan/systemtap/testsuite/systemtap.context/context_ns.exp ...
-PASS: pid_ns startup
-PASS: pid_ns load generation
-PASS: pid_ns shutdown and output
+FAIL: pid_ns startup (eof)
Running /home/sultan/systemtap/testsuite/systemtap.context/fib.exp ...
FAIL: fib (2 0)
FAIL: fib (10 0)
@@ -4353,7 +4341,7 @@
PASS: systemtap.examples/general/tcl-trace build
FAIL: systemtap.examples/general/tcl-trace run
PASS: systemtap.examples/general/varwatch build
-FAIL: systemtap.examples/general/varwatch run
+PASS: systemtap.examples/general/varwatch run
PASS: systemtap.examples/general/watchdog support
PASS: systemtap.examples/general/watchdog build
PASS: systemtap.examples/general/watchdog run
@@ -4865,15 +4853,15 @@
PASS: kprobes_onthefly - otf_start_disabled_iter_1 (valid output)
PASS: kprobes_onthefly - otf_start_enabled_iter_1 (valid output)
PASS: kprobes_onthefly - otf_start_disabled_iter_2 (valid output)
-FAIL: kprobes_onthefly - otf_start_enabled_iter_2 (invalid output)
-FAIL: kprobes_onthefly - otf_start_disabled_iter_3 (invalid output)
+PASS: kprobes_onthefly - otf_start_enabled_iter_2 (valid output)
+PASS: kprobes_onthefly - otf_start_disabled_iter_3 (valid output)
PASS: kprobes_onthefly - otf_start_enabled_iter_3 (valid output)
FAIL: kprobes_onthefly - otf_start_disabled_iter_4 (invalid output)
FAIL: kprobes_onthefly - otf_start_enabled_iter_4 (invalid output)
-FAIL: kprobes_onthefly - otf_start_disabled_iter_5 (invalid output)
+PASS: kprobes_onthefly - otf_start_disabled_iter_5 (valid output)
PASS: kprobes_onthefly - otf_start_enabled_iter_5 (valid output)
-FAIL: kprobes_onthefly - otf_timer_100ms (invalid output)
-PASS: kprobes_onthefly - otf_timer_50ms (valid output)
+PASS: kprobes_onthefly - otf_timer_100ms (valid output)
+FAIL: kprobes_onthefly - otf_timer_50ms (invalid output)
FAIL: kprobes_onthefly - otf_timer_10ms (invalid output)
PASS: kprobes_onthefly - otf_stress_5ms_iter_50 (survived)
PASS: kprobes_onthefly - otf_stress_1ms_iter_50 (survived)
@@ -4907,18 +4895,18 @@
Running /home/sultan/systemtap/testsuite/systemtap.onthefly/uprobes_onthefly.exp ...
PASS: uprobes_onthefly (compilation)
FAIL: uprobes_onthefly - otf_finish_at_start_disabled (invalid output)
-FAIL: uprobes_onthefly - otf_finish_at_start_enabled (stap)
+PASS: uprobes_onthefly - otf_finish_at_start_enabled (valid output)
FAIL: uprobes_onthefly - otf_start_disabled_iter_1 (invalid output)
FAIL: uprobes_onthefly - otf_start_enabled_iter_1 (invalid output)
-FAIL: uprobes_onthefly - otf_start_disabled_iter_2 (invalid output)
-FAIL: uprobes_onthefly - otf_start_enabled_iter_2 (invalid output)
+FAIL: uprobes_onthefly - otf_start_disabled_iter_2 (stap)
+FAIL: uprobes_onthefly - otf_start_enabled_iter_2 (stap)
FAIL: uprobes_onthefly - otf_start_disabled_iter_3 (invalid output)
FAIL: uprobes_onthefly - otf_start_enabled_iter_3 (invalid output)
FAIL: uprobes_onthefly - otf_start_disabled_iter_4 (invalid output)
FAIL: uprobes_onthefly - otf_start_enabled_iter_4 (stap)
FAIL: uprobes_onthefly - otf_start_disabled_iter_5 (invalid output)
-FAIL: uprobes_onthefly - otf_start_enabled_iter_5 (stap)
-FAIL: uprobes_onthefly - otf_timer_100ms (invalid output)
+FAIL: uprobes_onthefly - otf_start_enabled_iter_5 (invalid output)
+FAIL: uprobes_onthefly - otf_timer_100ms (stap)
FAIL: uprobes_onthefly - otf_timer_50ms (invalid output)
PASS: uprobes_onthefly - otf_stress_10ms_iter_50 (survived)
PASS: uprobes_onthefly - otf_stress_5ms_iter_50 (survived)
@@ -6976,7 +6964,7 @@
PASS: print_user_buffer compile
PASS: print_user_buffer startup
PASS: print_user_buffer load generation
-FAIL: print_user_buffer unexpected output
+PASS: print_user_buffer shutdown and output
Running /home/sultan/systemtap/testsuite/systemtap.printf/ptr-1.2.exp ...
PASS: systemtap.printf/ptr-1.2.stp --compatible=1.2
PASS: systemtap.printf/ptr-1.2.stp --compatible=1.2 -DSTP_LEGACY_PRINT
@@ -7083,7 +7071,7 @@
PASS: 32-bit access nd_syscall
PASS: 32-bit acct nd_syscall
PASS: 32-bit adjtimex nd_syscall
-FAIL: 32-bit aio nd_syscall
+PASS: 32-bit aio nd_syscall
FAIL: 32-bit alarm nd_syscall
PASS: 32-bit arch_prctl nd_syscall
PASS: 32-bit bind nd_syscall
@@ -7092,12 +7080,12 @@
PASS: 32-bit capability nd_syscall
PASS: 32-bit chmod nd_syscall
PASS: 32-bit chroot nd_syscall
-FAIL: 32-bit clock nd_syscall
-PASS: 32-bit clone nd_syscall
+PASS: 32-bit clock nd_syscall
+FAIL: 32-bit clone nd_syscall
PASS: 32-bit connect nd_syscall
FAIL: 32-bit copy_file_range nd_syscall
PASS: 32-bit dcookie nd_syscall
-FAIL: 32-bit dir nd_syscall
+PASS: 32-bit dir nd_syscall
PASS: 32-bit domainname nd_syscall
PASS: 32-bit dup nd_syscall
PASS: 32-bit eventfd nd_syscall
@@ -7105,7 +7093,7 @@
UNSUPPORTED: 32-bit execveat nd_syscall not supported on this arch
PASS: 32-bit exit nd_syscall
PASS: 32-bit exit_group nd_syscall
-FAIL: 32-bit fadvise64 nd_syscall
+PASS: 32-bit fadvise64 nd_syscall
PASS: 32-bit fallocate nd_syscall
PASS: 32-bit fanotify nd_syscall
PASS: 32-bit flock nd_syscall
@@ -7157,8 +7145,8 @@
UNSUPPORTED: 32-bit nice nd_syscall not supported on this arch
PASS: 32-bit numa nd_syscall
PASS: 32-bit openclose nd_syscall
-PASS: 32-bit perf_event nd_syscall
-PASS: 32-bit personality nd_syscall
+FAIL: 32-bit perf_event nd_syscall
+FAIL: 32-bit personality nd_syscall
PASS: 32-bit pgid nd_syscall
PASS: 32-bit pipe nd_syscall
PASS: 32-bit pivot_root nd_syscall
@@ -7168,7 +7156,7 @@
PASS: 32-bit pread nd_syscall
PASS: 32-bit preadv nd_syscall
PASS: 32-bit prlimit nd_syscall
-PASS: 32-bit process_vm nd_syscall
+FAIL: 32-bit process_vm nd_syscall
FAIL: 32-bit ptrace nd_syscall
PASS: 32-bit pwrite nd_syscall
PASS: 32-bit pwritev nd_syscall
@@ -7179,7 +7167,7 @@
PASS: 32-bit readwrite nd_syscall
PASS: 32-bit reboot nd_syscall
PASS: 32-bit recv nd_syscall
-FAIL: 32-bit recvfrom nd_syscall
+PASS: 32-bit recvfrom nd_syscall
PASS: 32-bit recvmmsg nd_syscall
PASS: 32-bit recvmsg nd_syscall
PASS: 32-bit remap_file_pages nd_syscall
@@ -7214,7 +7202,7 @@
PASS: 32-bit shmat nd_syscall
PASS: 32-bit shmget nd_syscall
PASS: 32-bit shutdown nd_syscall
-PASS: 32-bit sigaltstack nd_syscall
+FAIL: 32-bit sigaltstack nd_syscall
UNSUPPORTED: 32-bit sigmask nd_syscall not supported on this arch
PASS: 32-bit signal nd_syscall
PASS: 32-bit signalfd nd_syscall
@@ -7247,7 +7235,7 @@
PASS: 32-bit vforkwait nd_syscall
PASS: 32-bit vhangup nd_syscall
PASS: 32-bit wait nd_syscall
-PASS: 32-bit wait4 nd_syscall
+FAIL: 32-bit wait4 nd_syscall
PASS: 32-bit writev nd_syscall
PASS: 32-bit xattr nd_syscall
Running /home/sultan/systemtap/testsuite/systemtap.syscall/syscall_consistency.exp ...
@@ -7337,7 +7325,7 @@
PASS: 32-bit access syscall
PASS: 32-bit acct syscall
PASS: 32-bit adjtimex syscall
-FAIL: 32-bit aio syscall
+PASS: 32-bit aio syscall
FAIL: 32-bit alarm syscall
PASS: 32-bit arch_prctl syscall
PASS: 32-bit bind syscall
@@ -7346,9 +7334,9 @@
PASS: 32-bit capability syscall
PASS: 32-bit chmod syscall
PASS: 32-bit chroot syscall
-PASS: 32-bit clock syscall
+FAIL: 32-bit clock syscall
PASS: 32-bit clone syscall
-FAIL: 32-bit connect syscall
+PASS: 32-bit connect syscall
FAIL: 32-bit copy_file_range syscall
PASS: 32-bit dcookie syscall
PASS: 32-bit dir syscall
@@ -7359,7 +7347,7 @@
UNSUPPORTED: 32-bit execveat syscall not supported on this arch
PASS: 32-bit exit syscall
PASS: 32-bit exit_group syscall
-PASS: 32-bit fadvise64 syscall
+FAIL: 32-bit fadvise64 syscall
PASS: 32-bit fallocate syscall
PASS: 32-bit fanotify syscall
PASS: 32-bit flock syscall
@@ -7422,7 +7410,7 @@
PASS: 32-bit pread syscall
PASS: 32-bit preadv syscall
PASS: 32-bit prlimit syscall
-FAIL: 32-bit process_vm syscall
+PASS: 32-bit process_vm syscall
PASS: 32-bit ptrace syscall
PASS: 32-bit pwrite syscall
PASS: 32-bit pwritev syscall
@@ -7432,8 +7420,8 @@
PASS: 32-bit readv syscall
PASS: 32-bit readwrite syscall
PASS: 32-bit reboot syscall
-FAIL: 32-bit recv syscall
-FAIL: 32-bit recvfrom syscall
+PASS: 32-bit recv syscall
+PASS: 32-bit recvfrom syscall
PASS: 32-bit recvmmsg syscall
PASS: 32-bit recvmsg syscall
PASS: 32-bit remap_file_pages syscall
@@ -7479,7 +7467,7 @@
PASS: 32-bit swap syscall
PASS: 32-bit sync syscall
PASS: 32-bit sync_file_range syscall
-FAIL: 32-bit syncfs syscall
+PASS: 32-bit syncfs syscall
PASS: 32-bit sysctl syscall
PASS: 32-bit sysfs syscall
PASS: 32-bit sysinfo syscall
@@ -7500,7 +7488,7 @@
PASS: 32-bit userfaultfd syscall
PASS: 32-bit vforkwait syscall
PASS: 32-bit vhangup syscall
-FAIL: 32-bit wait syscall
+PASS: 32-bit wait syscall
FAIL: 32-bit wait4 syscall
PASS: 32-bit writev syscall
PASS: 32-bit xattr syscall
@@ -7538,7 +7526,7 @@
PASS: 32-bit fanotify tp_syscall
PASS: 32-bit flock tp_syscall
PASS: 32-bit forkwait tp_syscall
-FAIL: 32-bit futex tp_syscall
+PASS: 32-bit futex tp_syscall
PASS: 32-bit futimes tp_syscall
PASS: 32-bit fxattr tp_syscall
PASS: 32-bit getcpu tp_syscall
@@ -7586,7 +7574,7 @@
PASS: 32-bit numa tp_syscall
PASS: 32-bit openclose tp_syscall
FAIL: 32-bit perf_event tp_syscall
-PASS: 32-bit personality tp_syscall
+FAIL: 32-bit personality tp_syscall
PASS: 32-bit pgid tp_syscall
PASS: 32-bit pipe tp_syscall
PASS: 32-bit pivot_root tp_syscall
@@ -7597,7 +7585,7 @@
PASS: 32-bit preadv tp_syscall
PASS: 32-bit prlimit tp_syscall
FAIL: 32-bit process_vm tp_syscall
-PASS: 32-bit ptrace tp_syscall
+FAIL: 32-bit ptrace tp_syscall
PASS: 32-bit pwrite tp_syscall
PASS: 32-bit pwritev tp_syscall
PASS: 32-bit quotactl tp_syscall
@@ -7608,8 +7596,8 @@
PASS: 32-bit reboot tp_syscall
PASS: 32-bit recv tp_syscall
FAIL: 32-bit recvfrom tp_syscall
-PASS: 32-bit recvmmsg tp_syscall
-FAIL: 32-bit recvmsg tp_syscall
+FAIL: 32-bit recvmmsg tp_syscall
+PASS: 32-bit recvmsg tp_syscall
PASS: 32-bit remap_file_pages tp_syscall
PASS: 32-bit rename tp_syscall
PASS: 32-bit restart_syscall tp_syscall
@@ -7623,7 +7611,7 @@
PASS: 32-bit sched_setaffinity tp_syscall
PASS: 32-bit sched_setscheduler tp_syscall
PASS: 32-bit seccomp tp_syscall
-PASS: 32-bit select tp_syscall
+FAIL: 32-bit select tp_syscall
PASS: 32-bit semctl tp_syscall
PASS: 32-bit semget tp_syscall
PASS: 32-bit semop tp_syscall
@@ -7674,7 +7662,7 @@
PASS: 32-bit userfaultfd tp_syscall
PASS: 32-bit vforkwait tp_syscall
PASS: 32-bit vhangup tp_syscall
-FAIL: 32-bit wait tp_syscall
+PASS: 32-bit wait tp_syscall
PASS: 32-bit wait4 tp_syscall
PASS: 32-bit writev tp_syscall
PASS: 32-bit xattr tp_syscall
@@ -9082,7 +9070,7 @@
PASS: unprivileged myproc: --unprivileged process.library(string).function(number).exported
PASS: unprivileged myproc: --privilege=stapusr process.library(string).function(string)
PASS: unprivileged myproc: --unprivileged process.library(string).function(string).call
-PASS: unprivileged myproc: --privilege=stapusr process.library(string).function(string).inline
+FAIL: unprivileged myproc: --privilege=stapusr process.library(string).function(string).inline
PASS: unprivileged myproc: --unprivileged process.library(string).function(string).return
PASS: unprivileged myproc: --privilege=stapusr process.library(string).function(string).exported
PASS: unprivileged myproc: --unprivileged process.library(string).function(string).label(string)
@@ -9117,7 +9105,7 @@
UNTESTED: unprivileged myproc: --privilege=stapusr process(number).insn.block
KFAIL: unprivileged myproc: --privilege=stapusr process(number).statement(number).absolute (PRMS: INODE_UPROBES)
KFAIL: unprivileged myproc: --unprivileged process(number).statement(number).absolute.return (PRMS: INODE_UPROBES)
-PASS: unprivileged myproc: --privilege=stapusr process(number).syscall
+FAIL: unprivileged myproc: --privilege=stapusr process(number).syscall
PASS: unprivileged myproc: --unprivileged process(number).syscall.return
UNTESTED: unprivileged myproc: --privilege=stapusr process(number).thread.begin
UNTESTED: unprivileged myproc: --privilege=stapusr process(number).thread.end
@@ -9126,61 +9114,61 @@
PASS: unprivileged myproc: --privilege=stapusr process(number).function(number).exported
PASS: unprivileged myproc: --unprivileged process(number).function(number).return
PASS: unprivileged myproc: --privilege=stapusr process(number).function(string)
-FAIL: unprivileged myproc: --unprivileged process(number).function(string).call
+PASS: unprivileged myproc: --unprivileged process(number).function(string).call
PASS: unprivileged myproc: --privilege=stapusr process(number).function(string).callee(string)
PASS: unprivileged myproc: --unprivileged process(number).function(string).callee(string).call
PASS: unprivileged myproc: --privilege=stapusr process(number).function(string).callee(string).return
PASS: unprivileged myproc: --unprivileged process(number).function(string).callees
PASS: unprivileged myproc: --privilege=stapusr process(number).function(string).callees(number)
PASS: unprivileged myproc: --unprivileged process(number).function(string).exported
-FAIL: unprivileged myproc: --privilege=stapusr process(number).function(string).inline
+PASS: unprivileged myproc: --privilege=stapusr process(number).function(string).inline
PASS: unprivileged myproc: --unprivileged process(number).function(string).label(string)
-PASS: unprivileged myproc: --privilege=stapusr process(number).function(string).return
+FAIL: unprivileged myproc: --privilege=stapusr process(number).function(string).return
PASS: unprivileged myproc: --unprivileged process(number).mark(string)
PASS: unprivileged myproc: --privilege=stapusr process(number).plt
-PASS: unprivileged myproc: --unprivileged process(number).plt.return
-PASS: unprivileged myproc: --privilege=stapusr process(number).plt(string)
+FAIL: unprivileged myproc: --unprivileged process(number).plt.return
+FAIL: unprivileged myproc: --privilege=stapusr process(number).plt(string)
PASS: unprivileged myproc: --unprivileged process(number).plt(string).return
-PASS: unprivileged myproc: --privilege=stapusr process(number).provider(string).mark(string)
+FAIL: unprivileged myproc: --privilege=stapusr process(number).provider(string).mark(string)
PASS: unprivileged myproc: --unprivileged process(number).statement(number)
-FAIL: unprivileged myproc: --privilege=stapusr process(number).statement(number).nearest
+PASS: unprivileged myproc: --privilege=stapusr process(number).statement(number).nearest
PASS: unprivileged myproc: --unprivileged process(number).statement(string)
PASS: unprivileged myproc: --privilege=stapusr process(number).statement(string).nearest
-FAIL: unprivileged myproc: --unprivileged process(string).begin
+PASS: unprivileged myproc: --unprivileged process(string).begin
FAIL: unprivileged myproc: --privilege=stapusr process(string).end
PASS: unprivileged myproc: --unprivileged process(string).function(number)
PASS: unprivileged myproc: --privilege=stapusr process(string).function(number).call
KFAIL: unprivileged myproc: --unprivileged process(string).function(number).inline (PRMS: GCC)
PASS: unprivileged myproc: --privilege=stapusr process(string).function(number).return
-PASS: unprivileged myproc: --unprivileged process(string).function(number).exported
+FAIL: unprivileged myproc: --unprivileged process(string).function(number).exported
PASS: unprivileged myproc: --privilege=stapusr process(string).function(string)
PASS: unprivileged myproc: --unprivileged process(string).function(string).call
-PASS: unprivileged myproc: --privilege=stapusr process(string).function(string).inline
-PASS: unprivileged myproc: --unprivileged process(string).function(string).return
+FAIL: unprivileged myproc: --privilege=stapusr process(string).function(string).inline
+FAIL: unprivileged myproc: --unprivileged process(string).function(string).return
PASS: unprivileged myproc: --privilege=stapusr process(string).function(string).exported
PASS: unprivileged myproc: --unprivileged process(string).function(string).callee(string)
PASS: unprivileged myproc: --privilege=stapusr process(string).function(string).callee(string).call
PASS: unprivileged myproc: --unprivileged process(string).function(string).callee(string).return
-FAIL: unprivileged myproc: --privilege=stapusr process(string).function(string).callees
+PASS: unprivileged myproc: --privilege=stapusr process(string).function(string).callees
PASS: unprivileged myproc: --unprivileged process(string).function(string).callees(number)
UNTESTED: unprivileged myproc: --privilege=stapusr process(string).insn
UNTESTED: unprivileged myproc: --privilege=stapusr process(string).insn.block
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).function(number)
PASS: unprivileged myproc: --unprivileged process(string).library(string).function(number).call
KFAIL: unprivileged myproc: --privilege=stapusr process(string).library(string).function(number).inline (PRMS: GCC)
-PASS: unprivileged myproc: --unprivileged process(string).library(string).function(number).return
+FAIL: unprivileged myproc: --unprivileged process(string).library(string).function(number).return
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).function(number).exported
-PASS: unprivileged myproc: --unprivileged process(string).library(string).function(string)
+FAIL: unprivileged myproc: --unprivileged process(string).library(string).function(string)
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).function(string).call
PASS: unprivileged myproc: --unprivileged process(string).library(string).function(string).inline
-PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).function(string).return
+FAIL: unprivileged myproc: --privilege=stapusr process(string).library(string).function(string).return
PASS: unprivileged myproc: --unprivileged process(string).library(string).function(string).exported
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).function(string).label(string)
-PASS: unprivileged myproc: --unprivileged process(string).library(string).function(string).callee(string)
+FAIL: unprivileged myproc: --unprivileged process(string).library(string).function(string).callee(string)
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).function(string).callee(string).call
UNTESTED: unprivileged myproc: --unprivileged process(string).library(string).function(string).callee(string).return
PASS: unprivileged myproc: --unprivileged process(string).library(string).function(string).callees
-FAIL: unprivileged myproc: --privilege=stapusr process(string).library(string).function(string).callees(number)
+PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).function(string).callees(number)
PASS: unprivileged myproc: --unprivileged process(string).library(string).mark(string)
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).provider(string).mark(string)
PASS: unprivileged myproc: --unprivileged process(string).library(string).statement(number)
@@ -9191,17 +9179,17 @@
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).plt.return
PASS: unprivileged myproc: --unprivileged process(string).library(string).plt(string)
PASS: unprivileged myproc: --privilege=stapusr process(string).library(string).plt(string).return
-PASS: unprivileged myproc: --unprivileged process(string).mark(string)
-FAIL: unprivileged myproc: --privilege=stapusr process(string).provider(string).mark(string)
+FAIL: unprivileged myproc: --unprivileged process(string).mark(string)
+PASS: unprivileged myproc: --privilege=stapusr process(string).provider(string).mark(string)
PASS: unprivileged myproc: --unprivileged process(string).statement(number)
PASS: unprivileged myproc: --privilege=stapusr process(string).statement(number).nearest
PASS: unprivileged myproc: --unprivileged process(string).statement(string)
PASS: unprivileged myproc: --privilege=stapusr process(string).statement(string).nearest
PASS: unprivileged myproc: --unprivileged process(string).plt
-FAIL: unprivileged myproc: --privilege=stapusr process(string).plt.return
-FAIL: unprivileged myproc: --unprivileged process(string).plt(string)
+PASS: unprivileged myproc: --privilege=stapusr process(string).plt.return
+PASS: unprivileged myproc: --unprivileged process(string).plt(string)
PASS: unprivileged myproc: --privilege=stapusr process(string).plt(string).return
-FAIL: unprivileged myproc: --unprivileged process(string).syscall
+PASS: unprivileged myproc: --unprivileged process(string).syscall
PASS: unprivileged myproc: --privilege=stapusr process(string).syscall.return
PASS: unprivileged myproc: --unprivileged process(string).thread.begin
PASS: unprivileged myproc: --privilege=stapusr process(string).thread.end
@@ -9252,7 +9240,7 @@
PASS: unprivileged myproc: --privilege=stapsys process.library(string).provider(string).mark(string)
PASS: unprivileged myproc: --privilege=stapsys process.library(string).statement(number)
PASS: unprivileged myproc: --privilege=stapsys process.library(string).statement(number).nearest
-FAIL: unprivileged myproc: --privilege=stapsys process.library(string).statement(string)
+PASS: unprivileged myproc: --privilege=stapsys process.library(string).statement(string)
PASS: unprivileged myproc: --privilege=stapsys process.library(string).statement(string).nearest
PASS: unprivileged myproc: --privilege=stapsys process.provider(string).mark(string)
PASS: unprivileged myproc: --privilege=stapsys process.mark(string)
@@ -9279,7 +9267,7 @@
PASS: unprivileged myproc: --privilege=stapsys process(number).function(number).exported
PASS: unprivileged myproc: --privilege=stapsys process(number).function(number).return
PASS: unprivileged myproc: --privilege=stapsys process(number).function(string)
-PASS: unprivileged myproc: --privilege=stapsys process(number).function(string).call
+FAIL: unprivileged myproc: --privilege=stapsys process(number).function(string).call
PASS: unprivileged myproc: --privilege=stapsys process(number).function(string).callee(string)
PASS: unprivileged myproc: --privilege=stapsys process(number).function(string).callee(string).call
PASS: unprivileged myproc: --privilege=stapsys process(number).function(string).callee(string).return
@@ -9308,10 +9296,10 @@
PASS: unprivileged myproc: --privilege=stapsys process(string).function(number).exported
PASS: unprivileged myproc: --privilege=stapsys process(string).function(string)
PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).call
-PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).inline
+FAIL: unprivileged myproc: --privilege=stapsys process(string).function(string).inline
PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).return
PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).exported
-FAIL: unprivileged myproc: --privilege=stapsys process(string).function(string).callee(string)
+PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).callee(string)
PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).callee(string).call
PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).callee(string).return
PASS: unprivileged myproc: --privilege=stapsys process(string).function(string).callees
@@ -9324,7 +9312,7 @@
PASS: unprivileged myproc: --privilege=stapsys process(string).library(string).function(number).return
PASS: unprivileged myproc: --privilege=stapsys process(string).library(string).function(number).exported
PASS: unprivileged myproc: --privilege=stapsys process(string).library(string).function(string)
-FAIL: unprivileged myproc: --privilege=stapsys process(string).library(string).function(string).call
+PASS: unprivileged myproc: --privilege=stapsys process(string).library(string).function(string).call
PASS: unprivileged myproc: --privilege=stapsys process(string).library(string).function(string).inline
PASS: unprivileged myproc: --privilege=stapsys process(string).library(string).function(string).return
PASS: unprivileged myproc: --privilege=stapsys process(string).library(string).function(string).exported
@@ -10330,8 +10318,8 @@
=== systemtap Summary ===
-# of expected passes 8071
-# of unexpected failures 400
+# of expected passes 8060
+# of unexpected failures 396
# of unexpected successes 9
# of expected failures 346
# of known failures 82
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment