On Tue, Jul 08, 2014 at 03:16:43PM -0400, Steven Rostedt wrote: > On Mon, 07 Jul 2014 13:00:14 -0700 > <gregkh@xxxxxxxxxxxxxxxxxxx> 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 <stable@xxxxxxxxxxxxxxx>. > > > > 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)" <rostedt@xxxxxxxxxxx> > 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/5393DB61.6060707@xxxxxxxxxx > > Reported-by: Sasha Levin <sasha.levin@xxxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx # 3.10+ > Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx> > > --- > 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 majordomo@xxxxxxxxxxxxxxx > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html