• Salman Qazi's avatar
    perf: Use css_tryget() to avoid propping up css refcount · 9c5da09d
    Salman Qazi authored
    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 test-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: default avatarSalman Qazi <sqazi@google.com>
    Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
    Acked-by: default avatarTejun Heo <tj@kernel.org>
    Link: http://lkml.kernel.org/r/20120614223108.1025.2503.stgit@dungbeetle.mtv.corp.google.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
    9c5da09d
core.c 167 KB