diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-02-26 23:55:58 -0500 |
---|---|---|
committer | Steven Rostedt <srostedt@redhat.com> | 2009-02-26 23:55:58 -0500 |
commit | d8e83d26b5ab3b31ee0ff6d093a2627707a1e221 (patch) | |
tree | a8a24753ca24db4f3dd9bb887962e4cdcffac314 /kernel/trace/trace.c | |
parent | 577b785f55168d5acb3d123ba41bfe8d7981e044 (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.c | 20 |
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 | |||
2024 | tracing_trace_options_read(struct file *filp, char __user *ubuf, | 2024 | tracing_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 | } |