diff options
Diffstat (limited to 'tools/perf/util/thread.c')
| -rw-r--r-- | tools/perf/util/thread.c | 35 | 
1 files changed, 26 insertions, 9 deletions
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index b413ba5b9835..3e29a4e8b5e6 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -125,10 +125,27 @@ void thread__put(struct thread *thread)  {  	if (thread && refcount_dec_and_test(&thread->refcnt)) {  		/* -		 * Remove it from the dead_threads list, as last reference -		 * is gone. +		 * Remove it from the dead threads list, as last reference is +		 * gone, if it is in a dead threads list. +		 * +		 * We may not be there anymore if say, the machine where it was +		 * stored was already deleted, so we already removed it from +		 * the dead threads and some other piece of code still keeps a +		 * reference. +		 * +		 * This is what 'perf sched' does and finally drops it in +		 * perf_sched__lat(), where it calls perf_sched__read_events(), +		 * that processes the events by creating a session and deleting +		 * it, which ends up destroying the list heads for the dead +		 * threads, but before it does that it removes all threads from +		 * it using list_del_init(). +		 * +		 * So we need to check here if it is in a dead threads list and +		 * if so, remove it before finally deleting the thread, to avoid +		 * an use after free situation.  		 */ -		list_del_init(&thread->node); +		if (!list_empty(&thread->node)) +			list_del_init(&thread->node);  		thread__delete(thread);  	}  } @@ -141,13 +158,13 @@ static struct namespaces *__thread__namespaces(const struct thread *thread)  	return list_first_entry(&thread->namespaces_list, struct namespaces, list);  } -struct namespaces *thread__namespaces(const struct thread *thread) +struct namespaces *thread__namespaces(struct thread *thread)  {  	struct namespaces *ns; -	down_read((struct rw_semaphore *)&thread->namespaces_lock); +	down_read(&thread->namespaces_lock);  	ns = __thread__namespaces(thread); -	up_read((struct rw_semaphore *)&thread->namespaces_lock); +	up_read(&thread->namespaces_lock);  	return ns;  } @@ -271,13 +288,13 @@ static const char *__thread__comm_str(const struct thread *thread)  	return comm__str(comm);  } -const char *thread__comm_str(const struct thread *thread) +const char *thread__comm_str(struct thread *thread)  {  	const char *str; -	down_read((struct rw_semaphore *)&thread->comm_lock); +	down_read(&thread->comm_lock);  	str = __thread__comm_str(thread); -	up_read((struct rw_semaphore *)&thread->comm_lock); +	up_read(&thread->comm_lock);  	return str;  }  | 
