On Tue, Jul 08, 2014 at 03:16:43PM -0400, Steven Rostedt wrote:
> On Mon, 07 Jul 2014 13:00:14 -0700
> <[email protected]> wrote:
> 
> > 
> > The patch below does not apply to the 3.10-stable tree.
> > If someone wants it applied there, or to any other stable or longterm
> > tree, then please email the backport, including the original git commit
> > id to <[email protected]>.
> > 
> > thanks,
> > 
> > greg k-h
> > 
> 
> Here's the fix for 3.10 :
> 
> -- Steve
>

It looks like this backport could be used for the 3.11 kernel as
well.  Thanks!

Cheers,
--
Luís

> 
> ------------------ original commit in Linus's tree ------------------
> 
> >From 8b8b36834d0fff67fc8668093f4312dd04dcf21d Mon Sep 17 00:00:00 2001
> From: "Steven Rostedt (Red Hat)" <[email protected]>
> Date: Tue, 10 Jun 2014 09:46:00 -0400
> Subject: [PATCH] ring-buffer: Check if buffer exists before polling
> 
> The per_cpu buffers are created one per possible CPU. But these do
> not mean that those CPUs are online, nor do they even exist.
> 
> With the addition of the ring buffer polling, it assumes that the
> caller polls on an existing buffer. But this is not the case if
> the user reads trace_pipe from a CPU that does not exist, and this
> causes the kernel to crash.
> 
> Simple fix is to check the cpu against buffer bitmask against to see
> if the buffer was allocated or not and return -ENODEV if it is
> not.
> 
> More updates were done to pass the -ENODEV back up to userspace.
> 
> Link: http://lkml.kernel.org/r/[email protected]
> 
> Reported-by: Sasha Levin <[email protected]>
> Cc: [email protected] # 3.10+
> Signed-off-by: Steven Rostedt <[email protected]>
> 
> ---
>  include/linux/ring_buffer.h |    2 +-
>  kernel/trace/ring_buffer.c  |    5 ++++-
>  kernel/trace/trace.c        |   25 ++++++++++++++++++-------
>  kernel/trace/trace.h        |    4 ++--
>  4 files changed, 25 insertions(+), 11 deletions(-)
> 
> Index: linux-trace.git/include/linux/ring_buffer.h
> ===================================================================
> --- linux-trace.git.orig/include/linux/ring_buffer.h  2014-07-08 
> 15:08:37.214727623 -0400
> +++ linux-trace.git/include/linux/ring_buffer.h       2014-07-08 
> 15:08:39.860703457 -0400
> @@ -97,7 +97,7 @@
>       __ring_buffer_alloc((size), (flags), &__key);   \
>  })
>  
> -void ring_buffer_wait(struct ring_buffer *buffer, int cpu);
> +int ring_buffer_wait(struct ring_buffer *buffer, int cpu);
>  int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
>                         struct file *filp, poll_table *poll_table);
>  
> Index: linux-trace.git/kernel/trace/ring_buffer.c
> ===================================================================
> --- linux-trace.git.orig/kernel/trace/ring_buffer.c   2014-07-08 
> 15:08:37.217727595 -0400
> +++ linux-trace.git/kernel/trace/ring_buffer.c        2014-07-08 
> 15:08:39.862703439 -0400
> @@ -543,7 +543,7 @@
>   * as data is added to any of the @buffer's cpu buffers. Otherwise
>   * it will wait for data to be added to a specific cpu buffer.
>   */
> -void ring_buffer_wait(struct ring_buffer *buffer, int cpu)
> +int ring_buffer_wait(struct ring_buffer *buffer, int cpu)
>  {
>       struct ring_buffer_per_cpu *cpu_buffer;
>       DEFINE_WAIT(wait);
> @@ -557,6 +557,8 @@
>       if (cpu == RING_BUFFER_ALL_CPUS)
>               work = &buffer->irq_work;
>       else {
> +             if (!cpumask_test_cpu(cpu, buffer->cpumask))
> +                     return -ENODEV;
>               cpu_buffer = buffer->buffers[cpu];
>               work = &cpu_buffer->irq_work;
>       }
> @@ -591,6 +593,7 @@
>               schedule();
>  
>       finish_wait(&work->waiters, &wait);
> +     return 0;
>  }
>  
>  /**
> Index: linux-trace.git/kernel/trace/trace.c
> ===================================================================
> --- linux-trace.git.orig/kernel/trace/trace.c 2014-07-08 15:08:37.221727559 
> -0400
> +++ linux-trace.git/kernel/trace/trace.c      2014-07-08 15:08:39.865703412 
> -0400
> @@ -1027,13 +1027,13 @@
>  }
>  #endif /* CONFIG_TRACER_MAX_TRACE */
>  
> -static void default_wait_pipe(struct trace_iterator *iter)
> +static int default_wait_pipe(struct trace_iterator *iter)
>  {
>       /* Iterators are static, they should be filled or empty */
>       if (trace_buffer_iter(iter, iter->cpu_file))
> -             return;
> +             return 0;
>  
> -     ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
> +     return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
>  }
>  
>  #ifdef CONFIG_FTRACE_STARTUP_TEST
> @@ -4056,17 +4056,19 @@
>   *
>   *     Anyway, this is really very primitive wakeup.
>   */
> -void poll_wait_pipe(struct trace_iterator *iter)
> +int poll_wait_pipe(struct trace_iterator *iter)
>  {
>       set_current_state(TASK_INTERRUPTIBLE);
>       /* sleep for 100 msecs, and try again. */
>       schedule_timeout(HZ / 10);
> +     return 0;
>  }
>  
>  /* Must be called with trace_types_lock mutex held. */
>  static int tracing_wait_pipe(struct file *filp)
>  {
>       struct trace_iterator *iter = filp->private_data;
> +     int ret;
>  
>       while (trace_empty(iter)) {
>  
> @@ -4076,10 +4078,13 @@
>  
>               mutex_unlock(&iter->mutex);
>  
> -             iter->trace->wait_pipe(iter);
> +             ret = iter->trace->wait_pipe(iter);
>  
>               mutex_lock(&iter->mutex);
>  
> +             if (ret)
> +                     return ret;
> +
>               if (signal_pending(current))
>                       return -EINTR;
>  
> @@ -5013,8 +5018,12 @@
>                               goto out_unlock;
>                       }
>                       mutex_unlock(&trace_types_lock);
> -                     iter->trace->wait_pipe(iter);
> +                     ret = iter->trace->wait_pipe(iter);
>                       mutex_lock(&trace_types_lock);
> +                     if (ret) {
> +                             size = ret;
> +                             goto out_unlock;
> +                     }
>                       if (signal_pending(current)) {
>                               size = -EINTR;
>                               goto out_unlock;
> @@ -5226,8 +5235,10 @@
>                       goto out;
>               }
>               mutex_unlock(&trace_types_lock);
> -             iter->trace->wait_pipe(iter);
> +             ret = iter->trace->wait_pipe(iter);
>               mutex_lock(&trace_types_lock);
> +             if (ret)
> +                     goto out;
>               if (signal_pending(current)) {
>                       ret = -EINTR;
>                       goto out;
> Index: linux-trace.git/kernel/trace/trace.h
> ===================================================================
> --- linux-trace.git.orig/kernel/trace/trace.h 2014-07-08 15:08:37.223727540 
> -0400
> +++ linux-trace.git/kernel/trace/trace.h      2014-07-08 15:08:54.542569018 
> -0400
> @@ -342,7 +342,7 @@
>       void                    (*stop)(struct trace_array *tr);
>       void                    (*open)(struct trace_iterator *iter);
>       void                    (*pipe_open)(struct trace_iterator *iter);
> -     void                    (*wait_pipe)(struct trace_iterator *iter);
> +     int                     (*wait_pipe)(struct trace_iterator *iter);
>       void                    (*close)(struct trace_iterator *iter);
>       void                    (*pipe_close)(struct trace_iterator *iter);
>       ssize_t                 (*read)(struct trace_iterator *iter,
> @@ -557,7 +557,7 @@
>  
>  void tracing_iter_reset(struct trace_iterator *iter, int cpu);
>  
> -void poll_wait_pipe(struct trace_iterator *iter);
> +int poll_wait_pipe(struct trace_iterator *iter);
>  
>  void ftrace(struct trace_array *tr,
>                           struct trace_array_cpu *data,
> --
> To unsubscribe from this list: send the line "unsubscribe stable" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to