summaryrefslogtreecommitdiff
path: root/kernel/printk/printk.c
diff options
context:
space:
mode:
authorJohn Ogness <john.ogness@linutronix.de>2020-09-30 11:07:33 +0206
committerPetr Mladek <pmladek@suse.com>2020-09-30 13:30:28 +0200
commit59f8bcca1ef6a5326f7c127e11b949e745bfa230 (patch)
tree52d947f428b834079aa907ec10be9967376ab5a8 /kernel/printk/printk.c
parentf35efc78add6439a9fbe611f2dd517641e82d067 (diff)
printk: avoid and/or handle record truncation
If a reader provides a buffer that is smaller than the message text, the @text_len field of @info will have a value larger than the buffer size. If readers blindly read @text_len bytes of data without checking the size, they will read beyond their buffer. Add this check to record_print_text() to properly recognize when such truncation has occurred. Add a maximum size argument to the ringbuffer function to extend records so that records can not be created that are larger than the buffer size of readers. When extending records (LOG_CONT), do not extend records beyond LOG_LINE_MAX since that is the maximum size available in the buffers used by consoles and syslog. Fixes: f5f022e53b87 ("printk: reimplement log_cont using record extension") Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: John Ogness <john.ogness@linutronix.de> Reviewed-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20200930090134.8723-2-john.ogness@linutronix.de
Diffstat (limited to 'kernel/printk/printk.c')
-rw-r--r--kernel/printk/printk.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 1fe3d0cb2fe0..15cd73da0528 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1349,6 +1349,13 @@ static size_t record_print_text(struct printk_record *r, bool syslog,
size_t len = 0;
char *next;
+ /*
+ * If the message was truncated because the buffer was not large
+ * enough, treat the available text as if it were the full text.
+ */
+ if (text_len > buf_size)
+ text_len = buf_size;
+
prefix_len = info_print_prefix(r->info, syslog, time, prefix);
/*
@@ -1903,7 +1910,7 @@ static size_t log_output(int facility, int level, enum log_flags lflags,
struct printk_record r;
prb_rec_init_wr(&r, text_len);
- if (prb_reserve_in_last(&e, prb, &r, caller_id)) {
+ if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) {
memcpy(&r.text_buf[r.info->text_len], text, text_len);
r.info->text_len += text_len;
if (lflags & LOG_NEWLINE) {