| From: John Ogness <john.ogness@linutronix.de> |
| Date: Fri, 22 Feb 2019 23:02:44 +0100 |
| Subject: [PATCH] printk: devkmsg: llseek: reset clear if it is lost |
| |
| SEEK_DATA will seek to the last clear record. If this clear record |
| is no longer in the ring buffer, devkmsg_llseek() will go into an |
| infinite loop. Fix that by resetting the clear sequence if the old |
| clear record is no longer in the ring buffer. |
| |
| Signed-off-by: John Ogness <john.ogness@linutronix.de> |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| --- |
| kernel/printk/printk.c | 7 ++++++- |
| 1 file changed, 6 insertions(+), 1 deletion(-) |
| |
| --- a/kernel/printk/printk.c |
| +++ b/kernel/printk/printk.c |
| @@ -761,6 +761,7 @@ static loff_t devkmsg_llseek(struct file |
| { |
| struct devkmsg_user *user = file->private_data; |
| loff_t ret; |
| + u64 seq; |
| |
| if (!user) |
| return -EBADF; |
| @@ -783,7 +784,7 @@ static loff_t devkmsg_llseek(struct file |
| * changes no global state, and does not clear anything. |
| */ |
| for (;;) { |
| - prb_iter_init(&user->iter, &printk_rb, NULL); |
| + prb_iter_init(&user->iter, &printk_rb, &seq); |
| ret = prb_iter_seek(&user->iter, clear_seq); |
| if (ret > 0) { |
| /* seeked to clear seq */ |
| @@ -800,6 +801,10 @@ static loff_t devkmsg_llseek(struct file |
| break; |
| } |
| /* iterator invalid, start over */ |
| + |
| + /* reset clear_seq if it is no longer available */ |
| + if (seq > clear_seq) |
| + clear_seq = 0; |
| } |
| ret = 0; |
| break; |