Skip to content

Commit 522a110

Browse files
Liming WangIngo Molnar
authored andcommitted
function tracing: fix wrong position computing of stack_trace
Impact: make output of stack_trace complete if buffer overruns When read buffer overruns, the output of stack_trace isn't complete. When printing records with seq_printf in t_show, if the read buffer has overruned by the current record, then this record won't be printed to user space through read buffer, it will just be dropped in this printing. When next printing, t_start should return the "*pos"th record, which is the one dropped by previous printing, but it just returns (m->private + *pos)th record. Here we use a more sane method to implement seq_operations which can be found in kernel code. Thus we needn't initialize m->private. About testing, it's not easy to overrun read buffer, but we can use seq_printf to print more padding bytes in t_show, then it's easy to check whether or not records are lost. This commit has been tested on both condition of overrun and non overrun. Signed-off-by: Liming Wang <liming.wang@windriver.com> Acked-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
1 parent ed31348 commit 522a110

1 file changed

Lines changed: 15 additions & 9 deletions

File tree

kernel/trace/trace_stack.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,16 @@ static struct file_operations stack_max_size_fops = {
184184
static void *
185185
t_next(struct seq_file *m, void *v, loff_t *pos)
186186
{
187-
long i = (long)m->private;
187+
long i;
188188

189189
(*pos)++;
190190

191-
i++;
191+
if (v == SEQ_START_TOKEN)
192+
i = 0;
193+
else {
194+
i = *(long *)v;
195+
i++;
196+
}
192197

193198
if (i >= max_stack_trace.nr_entries ||
194199
stack_dump_trace[i] == ULONG_MAX)
@@ -201,12 +206,15 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
201206

202207
static void *t_start(struct seq_file *m, loff_t *pos)
203208
{
204-
void *t = &m->private;
209+
void *t = SEQ_START_TOKEN;
205210
loff_t l = 0;
206211

207212
local_irq_disable();
208213
__raw_spin_lock(&max_stack_lock);
209214

215+
if (*pos == 0)
216+
return SEQ_START_TOKEN;
217+
210218
for (; t && l < *pos; t = t_next(m, t, &l))
211219
;
212220

@@ -235,17 +243,19 @@ static int trace_lookup_stack(struct seq_file *m, long i)
235243

236244
static int t_show(struct seq_file *m, void *v)
237245
{
238-
long i = *(long *)v;
246+
long i;
239247
int size;
240248

241-
if (i < 0) {
249+
if (v == SEQ_START_TOKEN) {
242250
seq_printf(m, " Depth Size Location"
243251
" (%d entries)\n"
244252
" ----- ---- --------\n",
245253
max_stack_trace.nr_entries);
246254
return 0;
247255
}
248256

257+
i = *(long *)v;
258+
249259
if (i >= max_stack_trace.nr_entries ||
250260
stack_dump_trace[i] == ULONG_MAX)
251261
return 0;
@@ -275,10 +285,6 @@ static int stack_trace_open(struct inode *inode, struct file *file)
275285
int ret;
276286

277287
ret = seq_open(file, &stack_trace_seq_ops);
278-
if (!ret) {
279-
struct seq_file *m = file->private_data;
280-
m->private = (void *)-1;
281-
}
282288

283289
return ret;
284290
}

0 commit comments

Comments
 (0)