• L
    tracing: add trace_event_read_lock() · 4f535968
    Lai Jiangshan 提交于
    I found that there is nothing to protect event_hash in
    ftrace_find_event(). Rcu protects the event hashlist
    but not the event itself while we use it after its extraction
    through ftrace_find_event().
    
    This lack of a proper locking in this spot opens a race
    window between any event dereferencing and module removal.
    
    Eg:
    
    --Task A--
    
    print_trace_line(trace) {
      event = find_ftrace_event(trace)
    
    --Task B--
    
    trace_module_remove_events(mod) {
      list_trace_events_module(ev, mod) {
        unregister_ftrace_event(ev->event) {
          hlist_del(ev->event->node)
            list_del(....)
        }
      }
    }
    |--> module removed, the event has been dropped
    
    --Task A--
    
      event->print(trace); // Dereferencing freed memory
    
    If the event retrieved belongs to a module and this module
    is concurrently removed, we may end up dereferencing a data
    from a freed module.
    
    RCU could solve this, but it would add latency to the kernel and
    forbid tracers output callbacks to call any sleepable code.
    So this fix converts 'trace_event_mutex' to a read/write semaphore,
    and adds trace_event_read_lock() to protect ftrace_find_event().
    
    [ Impact: fix possible freed memory dereference in ftrace ]
    Signed-off-by: NLai Jiangshan <laijs@cn.fujitsu.com>
    Acked-by: NSteven Rostedt <rostedt@goodmis.org>
    LKML-Reference: <4A114806.7090302@cn.fujitsu.com>
    Signed-off-by: NFrederic Weisbecker <fweisbec@gmail.com>
    4f535968
trace.c 97.9 KB