Printk fixes for 5.11-rc5
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEESH4wyp42V4tXvYsjUqAMR0iAlPIFAmAJmRwACgkQUqAMR0iA lPLxAxAAgBEj8XqRiQh51mDyGCFkHR0NJ2WqSRa50HHhw/mCipwl40jwTsOol2xs REodcmswBBvZVApqtWlN+U24j3VaU0gyjpt9ndfkkG9c5PeKlpryGnlABd4Zw3SP m8NHkO2rQtdAgVm6AaNd17mYXtZV9a820SNhiDrqxylNDHR1DJW31MoQTpyY4SqE zcFyOFabA/zAc869IEnbpiZ8AO6n1lQCJa0C+D+mI70jgy7YEmD0eGkxRTpjoMDS ms/iTjelxfWHsuNzQ+85q/931hdz53/Ri3a+HHjDVZSL/e/yxRyr9sOM0XLPVQDy 2xoHbqTZo4YCYaWSj0ePuW9Sl2yzxuuDtovNEUyssjP+22YV9en9qiHgViZqW9HN saruWYZytnpGp4YMFChgen4rxd7jbdxZZzaYOJdJWy2aRn3MfDXrg7aO97MhU4HS TeHGee430VYrUc28Nzhnd+wGyAtPDVlGSnZdT+AIo+Uv4a4iK8ULv/58mTM2DvrJ Nzln/pwSBf7ddarO8pvdAggmsBAxyBEQ8NUPbeSwiZ2BEIRnO+hT7mDLZ/6TNY83 jeBDZP7hxo5MfDMhUPkoTdxlZxETnHFrihopChcHjtw+Gz1mb27n1iFactWaLirg J+E+/dKbdmxtcKyT3NoqGvcEj08pk/ImtuCPK11b23CzUFTkLrk= =l1hI -----END PGP SIGNATURE----- Merge tag 'printk-for-5.11-printk-rework-fixup' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux Pull printk fixes from Petr Mladek: - Fix line counting and buffer size calculation. Both regressions caused that a reader buffer might not get filled as much as possible. - Restore non-documented behavior of printk() reader API and make it official. It did not fill the last byte of the provided buffer before 5.10. Two architectures, powerpc and um, used it to add the trailing '\0'. There might theoretically be more callers depending on this behavior in userspace. * tag 'printk-for-5.11-printk-rework-fixup' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux: printk: fix buffer overflow potential for print_text() printk: fix kmsg_dump_get_buffer length calulations printk: ringbuffer: fix line counting
This commit is contained in:
commit
2561bbbe2e
@ -1291,11 +1291,16 @@ static size_t info_print_prefix(const struct printk_info *info, bool syslog,
|
||||
* done:
|
||||
*
|
||||
* - Add prefix for each line.
|
||||
* - Drop truncated lines that no longer fit into the buffer.
|
||||
* - Add the trailing newline that has been removed in vprintk_store().
|
||||
* - Drop truncated lines that do not longer fit into the buffer.
|
||||
* - Add a string terminator.
|
||||
*
|
||||
* Since the produced string is always terminated, the maximum possible
|
||||
* return value is @r->text_buf_size - 1;
|
||||
*
|
||||
* Return: The length of the updated/prepared text, including the added
|
||||
* prefixes and the newline. The dropped line(s) are not counted.
|
||||
* prefixes and the newline. The terminator is not counted. The dropped
|
||||
* line(s) are not counted.
|
||||
*/
|
||||
static size_t record_print_text(struct printk_record *r, bool syslog,
|
||||
bool time)
|
||||
@ -1338,26 +1343,31 @@ static size_t record_print_text(struct printk_record *r, bool syslog,
|
||||
|
||||
/*
|
||||
* Truncate the text if there is not enough space to add the
|
||||
* prefix and a trailing newline.
|
||||
* prefix and a trailing newline and a terminator.
|
||||
*/
|
||||
if (len + prefix_len + text_len + 1 > buf_size) {
|
||||
if (len + prefix_len + text_len + 1 + 1 > buf_size) {
|
||||
/* Drop even the current line if no space. */
|
||||
if (len + prefix_len + line_len + 1 > buf_size)
|
||||
if (len + prefix_len + line_len + 1 + 1 > buf_size)
|
||||
break;
|
||||
|
||||
text_len = buf_size - len - prefix_len - 1;
|
||||
text_len = buf_size - len - prefix_len - 1 - 1;
|
||||
truncated = true;
|
||||
}
|
||||
|
||||
memmove(text + prefix_len, text, text_len);
|
||||
memcpy(text, prefix, prefix_len);
|
||||
|
||||
/*
|
||||
* Increment the prepared length to include the text and
|
||||
* prefix that were just moved+copied. Also increment for the
|
||||
* newline at the end of this line. If this is the last line,
|
||||
* there is no newline, but it will be added immediately below.
|
||||
*/
|
||||
len += prefix_len + line_len + 1;
|
||||
|
||||
if (text_len == line_len) {
|
||||
/*
|
||||
* Add the trailing newline removed in
|
||||
* vprintk_store().
|
||||
* This is the last line. Add the trailing newline
|
||||
* removed in vprintk_store().
|
||||
*/
|
||||
text[prefix_len + line_len] = '\n';
|
||||
break;
|
||||
@ -1382,6 +1392,14 @@ static size_t record_print_text(struct printk_record *r, bool syslog,
|
||||
text_len -= line_len + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a buffer was provided, it will be terminated. Space for the
|
||||
* string terminator is guaranteed to be available. The terminator is
|
||||
* not counted in the return value.
|
||||
*/
|
||||
if (buf_size > 0)
|
||||
text[len] = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -3427,7 +3445,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
||||
while (prb_read_valid_info(prb, seq, &info, &line_count)) {
|
||||
if (r.info->seq >= dumper->next_seq)
|
||||
break;
|
||||
l += get_record_print_text_size(&info, line_count, true, time);
|
||||
l += get_record_print_text_size(&info, line_count, syslog, time);
|
||||
seq = r.info->seq + 1;
|
||||
}
|
||||
|
||||
@ -3437,7 +3455,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
||||
&info, &line_count)) {
|
||||
if (r.info->seq >= dumper->next_seq)
|
||||
break;
|
||||
l -= get_record_print_text_size(&info, line_count, true, time);
|
||||
l -= get_record_print_text_size(&info, line_count, syslog, time);
|
||||
seq = r.info->seq + 1;
|
||||
}
|
||||
|
||||
|
@ -1718,7 +1718,7 @@ static bool copy_data(struct prb_data_ring *data_ring,
|
||||
|
||||
/* Caller interested in the line count? */
|
||||
if (line_count)
|
||||
*line_count = count_lines(data, data_size);
|
||||
*line_count = count_lines(data, len);
|
||||
|
||||
/* Caller interested in the data content? */
|
||||
if (!buf || !buf_size)
|
||||
|
Loading…
Reference in New Issue
Block a user