Commit 3bfa7e14 authored by Vasily Averin's avatar Vasily Averin Committed by Linus Torvalds
Browse files

fs/seq_file.c: seq_read(): add info message about buggy .next functions

Patch series "seq_file .next functions should increase position index".

In Aug 2018 NeilBrown noticed commit 1f4aace6 ("fs/seq_file.c:
simplify seq_file iteration code and interface")

"Some ->next functions do not increment *pos when they return NULL...
Note that such ->next functions are buggy and should be fixed.  A simple
demonstration is dd if=/proc/swaps bs=1000 skip=1 Choose any block size
larger than the size of /proc/swaps.  This will always show the whole
last line of /proc/swaps"

Described problem is still actual.  If you make lseek into middle of
last output line following read will output end of last line and whole
last line once again.

  $ dd if=/proc/swaps bs=1  # usual output
  Filename				Type		Size	Used	Priority
  /dev/dm-0                             partition	4194812	97536	-2
  104+0 records in
  104+0 records out
  104 bytes copied

  $ dd if=/proc/swaps bs=40 skip=1    # last line was generated twice
  dd: /proc/swaps: cannot skip to specified offset
  v/dm-0                                partition	4194812	97536	-2
  /dev/dm-0                             partition	4194812	97536	-2
  3+1 records in
  3+1 records out
  131 bytes copied

There are lot of other affected files, I've found 30+ including
/proc/net/ip_tables_matches and /proc/sysvipc/*

I've sent patches into maillists of affected subsystems already, this
patch-set fixes the problem in files related to pstore, tracing, gcov,
sysvipc and other subsystems processed via linux-kernel@ mailing list

This patch (of 4):

Add debug code to seq_read() to detect missed or out-of-tree incorrect
.next seq_file functions.

[ s/pr_info/pr_info_ratelimited/, per Qian Cai]

Signed-off-by: default avatarVasily Averin <>
Signed-off-by: default avatarAndrew Morton <>
Cc: NeilBrown <>
Cc: Al Viro <>
Cc: Steven Rostedt <>
Cc: Davidlohr Bueso <>
Cc: Ingo Molnar <>
Cc: Manfred Spraul <>
Cc: Peter Oberparleiter <>
Cc: Waiman Long <>

Signed-off-by: default avatarLinus Torvalds <>
parent cb8d9937
...@@ -232,9 +232,12 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) ...@@ -232,9 +232,12 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
loff_t pos = m->index; loff_t pos = m->index;
p = m->op->next(m, p, &m->index); p = m->op->next(m, p, &m->index);
if (pos == m->index) if (pos == m->index) {
/* Buggy ->next function */ pr_info_ratelimited("buggy seq_file .next function %ps "
"did not updated position index\n",
m->index++; m->index++;
if (!p || IS_ERR(p)) { if (!p || IS_ERR(p)) {
err = PTR_ERR(p); err = PTR_ERR(p);
break; break;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment