[stable 2.6.33+] tracing: Fix potential out-of-bounds in trace_get_user()

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

 



I forgot to Cc stable on this patch (just went into Linus's tree).

effects 2.6.33+
Fixes: b63f39ea5033 ("tracing: create generic trace parser")

-- Steve


Commit:     057db8488b53d5e4faa0cedb2f39d4ae75dfbdbb
Parent: b9be6d026d327593784b042aab4fa27e2de9c825
Author:     Steven Rostedt <rostedt@xxxxxxxxxxx>
AuthorDate: Wed Oct 9 22:23:23 2013 -0400
Committer:  Steven Rostedt <rostedt@xxxxxxxxxxx>
CommitDate: Fri Oct 18 21:02:56 2013 -0400

    tracing: Fix potential out-of-bounds in trace_get_user()
    
    Andrey reported the following report:
    
    ERROR: AddressSanitizer: heap-buffer-overflow on address
    ffff8800359c99f3 ffff8800359c99f3 is located 0 bytes to the right
    of 243-byte region [ffff8800359c9900, ffff8800359c99f3) Accessed by
    thread T13003: #0 ffffffff810dd2da (asan_report_error+0x32a/0x440)
      #1 ffffffff810dc6b0 (asan_check_region+0x30/0x40)
      #2 ffffffff810dd4d3 (__tsan_write1+0x13/0x20)
      #3 ffffffff811cd19e (ftrace_regex_release+0x1be/0x260)
      #4 ffffffff812a1065 (__fput+0x155/0x360)
      #5 ffffffff812a12de (____fput+0x1e/0x30)
      #6 ffffffff8111708d (task_work_run+0x10d/0x140)
      #7 ffffffff810ea043 (do_exit+0x433/0x11f0)
      #8 ffffffff810eaee4 (do_group_exit+0x84/0x130)
      #9 ffffffff810eafb1 (SyS_exit_group+0x21/0x30)
      #10 ffffffff81928782 (system_call_fastpath+0x16/0x1b)
    
    Allocated by thread T5167:
      #0 ffffffff810dc778 (asan_slab_alloc+0x48/0xc0)
      #1 ffffffff8128337c (__kmalloc+0xbc/0x500)
      #2 ffffffff811d9d54 (trace_parser_get_init+0x34/0x90)
      #3 ffffffff811cd7b3 (ftrace_regex_open+0x83/0x2e0)
      #4 ffffffff811cda7d (ftrace_filter_open+0x2d/0x40)
      #5 ffffffff8129b4ff (do_dentry_open+0x32f/0x430)
      #6 ffffffff8129b668 (finish_open+0x68/0xa0)
      #7 ffffffff812b66ac (do_last+0xb8c/0x1710)
      #8 ffffffff812b7350 (path_openat+0x120/0xb50)
      #9 ffffffff812b8884 (do_filp_open+0x54/0xb0)
      #10 ffffffff8129d36c (do_sys_open+0x1ac/0x2c0)
      #11 ffffffff8129d4b7 (SyS_open+0x37/0x50)
      #12 ffffffff81928782 (system_call_fastpath+0x16/0x1b)
    
    Shadow bytes around the buggy address:
      ffff8800359c9700: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
      ffff8800359c9780: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
      ffff8800359c9800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      ffff8800359c9880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      ffff8800359c9900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>ffff8800359c9980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[03]fb
      ffff8800359c9a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      ffff8800359c9a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      ffff8800359c9b00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
      ffff8800359c9b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      ffff8800359c9c00: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap redzone:          fa
      Heap kmalloc redzone:  fb
      Freed heap region:     fd
      Shadow gap:            fe
    
    The out-of-bounds access happens on 'parser->buffer[parser->idx] =
    0;' 
    Although the crash happened in ftrace_regex_open() the real bug
    occurred in trace_get_user() where there's an incrementation to
    parser->idx without a check against the size. The way it is
    triggered is if userspace sends in 128 characters (EVENT_BUF_SIZE +
    1), the loop that reads the last character stores it and then
    breaks out because there is no more characters. Then the last
    character is read to determine what to do next, and the index is
    incremented without checking size. 
    Then the caller of trace_get_user() usually nulls out the last
    character with a zero, but since the index is equal to the size, it
    writes a nul character after the allocated space, which can corrupt
    memory. 
    Luckily, only root user has write access to this file.
    
    Link:
    http://lkml.kernel.org/r/20131009222323.04fd1a0d@xxxxxxxxxxxxxxxxxx 
    Reported-by: Andrey Konovalov <andreyknvl@xxxxxxxxxx>
    Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
---
 kernel/trace/trace.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d5f7c4d..063a92b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -843,9 +843,12 @@ int trace_get_user(struct trace_parser *parser,
const char __user *ubuf, if (isspace(ch)) {
 		parser->buffer[parser->idx] = 0;
 		parser->cont = false;
-	} else {
+	} else if (parser->idx < parser->size - 1) {
 		parser->cont = true;
 		parser->buffer[parser->idx++] = ch;
+	} else {
+		ret = -EINVAL;
+		goto out;
 	}
 
 	*ppos += read;
--
To unsubscribe from this list: send the line "unsubscribe
git-commits-head" in the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
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]