Thread (4 messages) 4 messages, 3 authors, 2019-10-14

Re: [PATCH] perf_event: Add support for LSM and SELinux checks

From: Joel Fernandes <hidden>
Date: 2019-10-14 16:54:42
Also in: bpf, lkml, selinux

On Mon, Oct 14, 2019 at 11:35:44AM +0200, Peter Zijlstra wrote:
On Fri, Oct 11, 2019 at 12:03:30PM -0400, Joel Fernandes (Google) wrote:
quoted
@@ -4761,6 +4762,7 @@ int perf_event_release_kernel(struct perf_event *event)
 	}
 
 no_ctx:
+	security_perf_event_free(event);
 	put_event(event); /* Must be the 'last' reference */
 	return 0;
 }
quoted
@@ -10553,11 +10568,16 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 		}
 	}
 
+	err = security_perf_event_alloc(event);
+	if (err)
+		goto err_security;
+
 	/* symmetric to unaccount_event() in _free_event() */
 	account_event(event);
 
 	return event;
 
+err_security:
 err_addr_filters:
 	kfree(event->addr_filter_ranges);
 
There's a bunch of problems here I think:

 - err_security is named wrong; the naming scheme is to name the label
   after the last thing that succeeded / first thing that needs to be
   undone.

 - per that, you're forgetting to undo 'get_callchain_buffers()'
Yes, you're right. Tested your fix below. Sorry to miss this.
 - perf_event_release_kernel() is not a full match to
   perf_event_alloc(), inherited events get created by
   perf_event_alloc() but never pass through
   perf_event_release_kernel().
Oh, through inherit_event(). Thanks for pointing this semantic out, did not
know that.
I'm thinking the below patch on top should ammend these issues; please
verify.
Yes, applied your diff below and verified that the events are getting freed
as they were in my initial set of tests. The diff also looks good to me.

I squashed your diff below and will resend as v3. Since you modified this
patch a lot, I will add your Co-developed-by tag as well.

thanks, Peter!

 - Joel

quoted hunk ↗ jump to hunk
---
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4540,6 +4540,8 @@ static void _free_event(struct perf_even
 
 	unaccount_event(event);
 
+	security_perf_event_free(event);
+
 	if (event->rb) {
 		/*
 		 * Can happen when we close an event with re-directed output.
@@ -4774,7 +4776,6 @@ int perf_event_release_kernel(struct per
 	}
 
 no_ctx:
-	security_perf_event_free(event);
 	put_event(event); /* Must be the 'last' reference */
 	return 0;
 }
@@ -10595,14 +10596,18 @@ perf_event_alloc(struct perf_event_attr
 
 	err = security_perf_event_alloc(event);
 	if (err)
-		goto err_security;
+		goto err_callchain_buffer;
 
 	/* symmetric to unaccount_event() in _free_event() */
 	account_event(event);
 
 	return event;
 
-err_security:
+err_callchain_buffer:
+	if (!event->parent) {
+		if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
+			put_callchain_buffers();
+	}
 err_addr_filters:
 	kfree(event->addr_filter_ranges);
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help