diff options
author | John Ogness <john.ogness@linutronix.de> | 2020-09-30 11:07:33 +0206 |
---|---|---|
committer | Petr Mladek <pmladek@suse.com> | 2020-09-30 13:30:28 +0200 |
commit | 59f8bcca1ef6a5326f7c127e11b949e745bfa230 (patch) | |
tree | 52d947f428b834079aa907ec10be9967376ab5a8 /kernel/printk/printk.c | |
parent | f35efc78add6439a9fbe611f2dd517641e82d067 (diff) | |
download | lwn-59f8bcca1ef6a5326f7c127e11b949e745bfa230.tar.gz lwn-59f8bcca1ef6a5326f7c127e11b949e745bfa230.zip |
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.c | 9 |
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) { |