aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-26 23:55:58 -0500
committerSteven Rostedt <srostedt@redhat.com>2009-02-26 23:55:58 -0500
commitd8e83d26b5ab3b31ee0ff6d093a2627707a1e221 (patch)
treea8a24753ca24db4f3dd9bb887962e4cdcffac314 /kernel/trace/trace.c
parent577b785f55168d5acb3d123ba41bfe8d7981e044 (diff)
tracing: add protection around open use of current_tracer
Impact: fix to possible race conditions There's some uses of current_tracer that is not protected by the trace_types_lock. There is a small chance that a sysadmin changes the tracer while the current_tracer is being referenced. If the race is hit, it is unlikely to cause any harm since the tracers are constant and are not freed. But some strang side effects may occur. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 485c6e7f4465..6c89ec6cbd48 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2024,12 +2024,12 @@ static ssize_t
2024tracing_trace_options_read(struct file *filp, char __user *ubuf, 2024tracing_trace_options_read(struct file *filp, char __user *ubuf,
2025 size_t cnt, loff_t *ppos) 2025 size_t cnt, loff_t *ppos)
2026{ 2026{
2027 int i; 2027 struct tracer_opt *trace_opts;
2028 u32 tracer_flags;
2029 int len = 0;
2028 char *buf; 2030 char *buf;
2029 int r = 0; 2031 int r = 0;
2030 int len = 0; 2032 int i;
2031 u32 tracer_flags = current_trace->flags->val;
2032 struct tracer_opt *trace_opts = current_trace->flags->opts;
2033 2033
2034 2034
2035 /* calculate max size */ 2035 /* calculate max size */
@@ -2038,6 +2038,10 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
2038 len += 3; /* "no" and space */ 2038 len += 3; /* "no" and space */
2039 } 2039 }
2040 2040
2041 mutex_lock(&trace_types_lock);
2042 tracer_flags = current_trace->flags->val;
2043 trace_opts = current_trace->flags->opts;
2044
2041 /* 2045 /*
2042 * Increase the size with names of options specific 2046 * Increase the size with names of options specific
2043 * of the current tracer. 2047 * of the current tracer.
@@ -2049,8 +2053,10 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
2049 2053
2050 /* +2 for \n and \0 */ 2054 /* +2 for \n and \0 */
2051 buf = kmalloc(len + 2, GFP_KERNEL); 2055 buf = kmalloc(len + 2, GFP_KERNEL);
2052 if (!buf) 2056 if (!buf) {
2057 mutex_unlock(&trace_types_lock);
2053 return -ENOMEM; 2058 return -ENOMEM;
2059 }
2054 2060
2055 for (i = 0; trace_options[i]; i++) { 2061 for (i = 0; trace_options[i]; i++) {
2056 if (trace_flags & (1 << i)) 2062 if (trace_flags & (1 << i))
@@ -2067,6 +2073,7 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
2067 r += sprintf(buf + r, "no%s ", 2073 r += sprintf(buf + r, "no%s ",
2068 trace_opts[i].name); 2074 trace_opts[i].name);
2069 } 2075 }
2076 mutex_unlock(&trace_types_lock);
2070 2077
2071 r += sprintf(buf + r, "\n"); 2078 r += sprintf(buf + r, "\n");
2072 WARN_ON(r >= len + 2); 2079 WARN_ON(r >= len + 2);
@@ -2074,7 +2081,6 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
2074 r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 2081 r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2075 2082
2076 kfree(buf); 2083 kfree(buf);
2077
2078 return r; 2084 return r;
2079} 2085}
2080 2086
@@ -2149,7 +2155,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2149 2155
2150 /* If no option could be set, test the specific tracer options */ 2156 /* If no option could be set, test the specific tracer options */
2151 if (!trace_options[i]) { 2157 if (!trace_options[i]) {
2158 mutex_lock(&trace_types_lock);
2152 ret = set_tracer_option(current_trace, cmp, neg); 2159 ret = set_tracer_option(current_trace, cmp, neg);
2160 mutex_unlock(&trace_types_lock);
2153 if (ret) 2161 if (ret)
2154 return ret; 2162 return ret;
2155 } 2163 }