Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8dd9174 authored by Prateek Sood's avatar Prateek Sood Committed by Gerrit - the friendly Code Review server
Browse files

trace: fix race in perf_trace_buf initialization



A race condition exists while initialiazing perf_trace_buf from
perf_trace_init() and perf_kprobe_init().

      CPU0                                        CPU1
perf_trace_init()
  mutex_lock(&event_mutex)
    perf_trace_event_init()
      perf_trace_event_reg()
        total_ref_count == 0
	buf = alloc_percpu()
        perf_trace_buf[i] = buf
        tp_event->class->reg() //fails       perf_kprobe_init()
	goto fail                              perf_trace_event_init()
                                                 perf_trace_event_reg()
        fail:
	  total_ref_count == 0

                                                   total_ref_count == 0
                                                   buf = alloc_percpu()
                                                   perf_trace_buf[i] = buf
                                                   tp_event->class->reg()
                                                   total_ref_count++

          free_percpu(perf_trace_buf[i])
          perf_trace_buf[i] = NULL

Any subsequent call to perf_trace_event_reg() will observe
total_ref_count > 0, causing the perf_trace_buf to be NULL
always. This can result in perf_trace_buf getting accessed
from perf_trace_buf_alloc() without being initialized.

Acquiring event_mutex in perf_kprobe_init() before calling
perf_trace_event_init() should fix this race.

Change-Id: Ifa626940d86c574a15c554a0aef4a83d4b989698
Signed-off-by: default avatarPrateek Sood <prsood@codeaurora.org>
parent 7d456b7a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -272,9 +272,11 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe)
		goto out;
	}

	mutex_lock(&event_mutex);
	ret = perf_trace_event_init(tp_event, p_event);
	if (ret)
		destroy_local_trace_kprobe(tp_event);
	mutex_unlock(&event_mutex);
out:
	kfree(func);
	return ret;
@@ -282,8 +284,10 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe)

void perf_kprobe_destroy(struct perf_event *p_event)
{
	mutex_lock(&event_mutex);
	perf_trace_event_close(p_event);
	perf_trace_event_unreg(p_event);
	mutex_unlock(&event_mutex);

	destroy_local_trace_kprobe(p_event->tp_event);
}