[PATCH v3] printk: Fix discarding of records

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Found another buffer overflow in this code that was introduced by
e3756477aec028427fec767957c0d4b6cfb87208 trying to solve a related overflow.

strace still shows a problem:

	syslog(0x3, 0x7fffd65375d0, 0x1000)     = 4107

The first record output was in the middle of a LOG_CONT line:

	<4>[    2.974999] 0x0000000000000500-0x000000000000052f SystemIO conflicts with Region \GPIO 1 (20130328/utaddress-251)

This happens because when discarding records to be less than size, the first
line may expand due to there being no previous record. So we must use prev = 0
to calculate if it fits or we should continue discarding.

v3: fix whitespace
v2: fix loop properly

CC: stable@xxxxxxxxxxxxxxx
Signed-off-by: Debabrata Banerjee <dbanerje@xxxxxxxxxx>
---
 kernel/printk/printk.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b1d255f..e95c7b4 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1063,13 +1063,17 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
 		seq = clear_seq;
 		idx = clear_idx;
 		prev = 0;
-		while (len > size && seq < log_next_seq) {
+		while (seq < log_next_seq) {
 			struct printk_log *msg = log_from_idx(idx);
 
-			len -= msg_print_text(msg, prev, true, NULL, 0);
-			prev = msg->flags;
 			idx = log_next(idx);
 			seq++;
+
+			if (len - msg_print_text(msg, 0, true, NULL, 0) <= size)
+				break;
+
+			len -= msg_print_text(msg, prev, true, NULL, 0);
+			prev = msg->flags;
 		}
 
 		/* last message fitting into this dump */
@@ -2774,12 +2778,16 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
 	seq = dumper->cur_seq;
 	idx = dumper->cur_idx;
 	prev = 0;
-	while (l > size && seq < dumper->next_seq) {
+	while (seq < dumper->next_seq) {
 		struct printk_log *msg = log_from_idx(idx);
 
-		l -= msg_print_text(msg, prev, true, NULL, 0);
 		idx = log_next(idx);
 		seq++;
+
+		if (l - msg_print_text(msg, 0, true, NULL, 0) <= size)
+			break;
+
+		l -= msg_print_text(msg, prev, true, NULL, 0);
 		prev = msg->flags;
 	}
 
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]