The second loop of syslog_print_all() subtracts lengths that were added in the first loop. With commit b031a684bfd0 ("printk: remove logbuf_lock writer-protection of ringbuffer") it is possible that records are (over)written during syslog_print_all(). This allows the possibility of the second loop subtracting lengths that were never added in the first loop. This situation can result in syslog_print_all() filling the buffer starting from a later record, even though there may have been room to fit the earlier record(s) as well.
Unified · Split
| @@ -1494,6 +1494,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) · 1493 unmodified lines | |||
| 1494 | struct printk_info info; | 1494 | struct printk_info info; |
| 1495 | unsigned int line_count; | 1495 | unsigned int line_count; |
| 1496 | struct printk_record r; | 1496 | struct printk_record r; |
| 1497 | u64 max_seq; | ||
| 1497 | char *text; | 1498 | char *text; |
| 1498 | int len = 0; | 1499 | int len = 0; |
| 1499 | u64 seq; | 1500 | u64 seq; |
| @@ -1512,9 +1513,15 @@ static int syslog_print_all(char __user *buf, int size, bool clear) · 12 unmodified lines | |||
| 1512 | prb_for_each_info(clear_seq, prb, seq, &info, &line_count) | 1513 | prb_for_each_info(clear_seq, prb, seq, &info, &line_count) |
| 1513 | len += get_record_print_text_size(&info, line_count, true, time); | 1514 | len += get_record_print_text_size(&info, line_count, true, time); |
| 1514 | 1515 | ||
| 1516 | /* | ||
| 1517 | * Set an upper bound for the next loop to avoid subtracting lengths | ||
| 1518 | * that were never added. | ||
| 1519 | */ | ||
| 1520 | max_seq = seq; | ||
| 1521 | |||
| 1515 | /* move first record forward until length fits into the buffer */ | 1522 | /* move first record forward until length fits into the buffer */ |
| 1516 | prb_for_each_info(clear_seq, prb, seq, &info, &line_count) { | 1523 | prb_for_each_info(clear_seq, prb, seq, &info, &line_count) { |
| 1517 | if (len <= size) | 1524 | if (len <= size || info.seq >= max_seq) |
| 1518 | break; | 1525 | break; |
| 1519 | len -= get_record_print_text_size(&info, line_count, true, time); | 1526 | len -= get_record_print_text_size(&info, line_count, true, time); |
| 1520 | } | 1527 | } |