cgroups.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] perf: Use css_tryget to avoid propping up css refcount.
@ 2012-06-14 22:31 Salman Qazi
       [not found] ` <20120614223108.1025.2503.stgit-Oz2bD8w/QAX+Wsei8lUk51LMcqb5oVE02SarAXORi/o@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Salman Qazi @ 2012-06-14 22:31 UTC (permalink / raw)
  To: tj-DgEjT+Ai2ygdnm+yROfE0A, a.p.zijlstra-/NLkJaSkS4VmR6Xm/wNWPw
  Cc: cgroups-u79uwXL29TY76Z2rM5mHXA

An rmdir pushes css's ref count to zero.  However, if the associated
directory is open at the time, the dentry ref count is non-zero.  If
the fd for this directory is then passed into perf_event_open, it
does a css_get().  This bounces the ref count back up from zero.  This
is a problem by itself.  But what makes it turn into a crash is the
fact that we end up doing an extra dput, since we perform a dput
when css_put sees the ref count go down to zero.

css_tryget does not fall into that trap. So, we use that instead.

Reproduction case for the bug:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/unistd.h>
#include <linux/perf_event.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#define PERF_FLAG_PID_CGROUP    (1U << 2)

int perf_event_open(struct perf_event_attr *hw_event_uptr,
                    pid_t pid, int cpu, int group_fd, unsigned long flags) {
  return syscall(__NR_perf_event_open,hw_event_uptr, pid, cpu,
                 group_fd, flags);
}

/* Directly poke at the perf_event bug, since it's proving hard to repro
 * depending on where in the kernel tree.  what moved?
 */
int main(int argc, char **argv)
{
        int fd;
        struct perf_event_attr attr;
        memset(&attr, 0, sizeof(attr));
        attr.exclude_kernel = 1;
        attr.size = sizeof(attr);
        mkdir("/dev/cgroup/perf_event/blah", 0777);
        fd = open("/dev/cgroup/perf_event/blah", O_RDONLY);
        perror("open");
        rmdir("/dev/cgroup/perf_event/blah");
        sleep(2);
        perf_event_open(&attr, fd, 0, -1,  PERF_FLAG_PID_CGROUP);
        perror("perf_event_open");
        close(fd);
        return 0;
}

Signed-off-by: Salman Qazi <sqazi-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
 kernel/events/core.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index f85c015..d7d71d6 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -253,9 +253,9 @@ perf_cgroup_match(struct perf_event *event)
 	return !event->cgrp || event->cgrp == cpuctx->cgrp;
 }
 
-static inline void perf_get_cgroup(struct perf_event *event)
+static inline bool perf_tryget_cgroup(struct perf_event *event)
 {
-	css_get(&event->cgrp->css);
+	return css_tryget(&event->cgrp->css);
 }
 
 static inline void perf_put_cgroup(struct perf_event *event)
@@ -484,7 +484,11 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
 	event->cgrp = cgrp;
 
 	/* must be done before we fput() the file */
-	perf_get_cgroup(event);
+	if (!perf_tryget_cgroup(event)) {
+		event->cgrp = NULL;
+		ret = -ENOENT;
+		goto out;
+	}
 
 	/*
 	 * all events in a group must monitor

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] perf: Use css_tryget to avoid propping up css refcount.
       [not found] ` <20120614223108.1025.2503.stgit-Oz2bD8w/QAX+Wsei8lUk51LMcqb5oVE02SarAXORi/o@public.gmane.org>
@ 2012-06-15  1:40   ` Tejun Heo
       [not found]     ` <20120615014007.GA12624-9pTldWuhBndy/B6EtB590w@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Tejun Heo @ 2012-06-15  1:40 UTC (permalink / raw)
  To: Salman Qazi
  Cc: a.p.zijlstra-/NLkJaSkS4VmR6Xm/wNWPw,
	cgroups-u79uwXL29TY76Z2rM5mHXA

On Thu, Jun 14, 2012 at 03:31:09PM -0700, Salman Qazi wrote:
> An rmdir pushes css's ref count to zero.  However, if the associated
> directory is open at the time, the dentry ref count is non-zero.  If
> the fd for this directory is then passed into perf_event_open, it
> does a css_get().  This bounces the ref count back up from zero.  This
> is a problem by itself.  But what makes it turn into a crash is the
> fact that we end up doing an extra dput, since we perform a dput
> when css_put sees the ref count go down to zero.
> 
> css_tryget does not fall into that trap. So, we use that instead.
> 
...
> Signed-off-by: Salman Qazi <sqazi-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>

Acked-by: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

Peter, can you please pick up this one?

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] perf: Use css_tryget to avoid propping up css refcount.
       [not found]     ` <20120615014007.GA12624-9pTldWuhBndy/B6EtB590w@public.gmane.org>
@ 2012-06-15  6:32       ` Peter Zijlstra
  0 siblings, 0 replies; 3+ messages in thread
From: Peter Zijlstra @ 2012-06-15  6:32 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Salman Qazi, cgroups-u79uwXL29TY76Z2rM5mHXA

On Fri, 2012-06-15 at 10:40 +0900, Tejun Heo wrote:
> Peter, can you please pick up this one?

Done, thanks!

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-06-15  6:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-14 22:31 [PATCH] perf: Use css_tryget to avoid propping up css refcount Salman Qazi
     [not found] ` <20120614223108.1025.2503.stgit-Oz2bD8w/QAX+Wsei8lUk51LMcqb5oVE02SarAXORi/o@public.gmane.org>
2012-06-15  1:40   ` Tejun Heo
     [not found]     ` <20120615014007.GA12624-9pTldWuhBndy/B6EtB590w@public.gmane.org>
2012-06-15  6:32       ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).