Skip to content

Commit

Permalink
syslog: fill buffer with more than a single message for SYSLOG_ACTION…
Browse files Browse the repository at this point in the history
…_READ

The recent changes to the printk buffer management resulted in
SYSLOG_ACTION_READ to only return a single message, whereas previously
the buffer would get filled as much as possible. As, when too small to
fit everything, filling it to the last byte would be pretty ugly with
the new code, the patch arranges for as many messages as possible to
get returned in a single invocation. User space tools in at least all
SLES versions depend on the old behavior.

This at once addresses the issue attempted to get fixed with commit
b56a39a ("printk: return -EINVAL if
the message len is bigger than the buf size"), and since that commit
widened the possibility for losing a message altogether, the patch
here assumes that this other commit would get reverted first
(otherwise the patch here won't apply).

Furthermore, this patch also addresses the problem dealt with in
commit 4a77a5a ("printk: use mutex
lock to stop syslog_seq from going wild"), so I'd recommend reverting
that one too (albeit there's no direct collision between the two).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Kay Sievers <kay@vrfy.org>
Cc: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jan Beulich authored and Greg Kroah-Hartman committed Jun 26, 2012
1 parent 6fda135 commit 116e90b
Showing 1 changed file with 37 additions and 14 deletions.
51 changes: 37 additions & 14 deletions kernel/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,26 +862,49 @@ static int syslog_print(char __user *buf, int size)
{
char *text;
struct log *msg;
int len;
int len = 0;

text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
if (!text)
return -ENOMEM;

raw_spin_lock_irq(&logbuf_lock);
if (syslog_seq < log_first_seq) {
/* messages are gone, move to first one */
syslog_seq = log_first_seq;
syslog_idx = log_first_idx;
}
msg = log_from_idx(syslog_idx);
len = msg_print_text(msg, true, text, LOG_LINE_MAX);
syslog_idx = log_next(syslog_idx);
syslog_seq++;
raw_spin_unlock_irq(&logbuf_lock);
while (size > 0) {
size_t n;

raw_spin_lock_irq(&logbuf_lock);
if (syslog_seq < log_first_seq) {
/* messages are gone, move to first one */
syslog_seq = log_first_seq;
syslog_idx = log_first_idx;
}
if (syslog_seq == log_next_seq) {
raw_spin_unlock_irq(&logbuf_lock);
break;
}
msg = log_from_idx(syslog_idx);
n = msg_print_text(msg, true, text, LOG_LINE_MAX);
if (n <= size) {
syslog_idx = log_next(syslog_idx);
syslog_seq++;
} else
n = 0;
raw_spin_unlock_irq(&logbuf_lock);

if (!n)
break;

if (len > 0 && copy_to_user(buf, text, len))
len = -EFAULT;
len += n;
size -= n;
buf += n;
n = copy_to_user(buf - n, text, n);

if (n) {
len -= n;
if (!len)
len = -EFAULT;
break;
}
}

kfree(text);
return len;
Expand Down

0 comments on commit 116e90b

Please sign in to comment.