diff options
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 230 |
1 files changed, 89 insertions, 141 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 9f46e98ba8f2..243f6834d026 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -35,12 +35,17 @@ struct trace_probe { | |||
| 35 | const char *symbol; /* symbol name */ | 35 | const char *symbol; /* symbol name */ |
| 36 | struct ftrace_event_class class; | 36 | struct ftrace_event_class class; |
| 37 | struct ftrace_event_call call; | 37 | struct ftrace_event_call call; |
| 38 | struct ftrace_event_file * __rcu *files; | 38 | struct list_head files; |
| 39 | ssize_t size; /* trace entry size */ | 39 | ssize_t size; /* trace entry size */ |
| 40 | unsigned int nr_args; | 40 | unsigned int nr_args; |
| 41 | struct probe_arg args[]; | 41 | struct probe_arg args[]; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | struct event_file_link { | ||
| 45 | struct ftrace_event_file *file; | ||
| 46 | struct list_head list; | ||
| 47 | }; | ||
| 48 | |||
| 44 | #define SIZEOF_TRACE_PROBE(n) \ | 49 | #define SIZEOF_TRACE_PROBE(n) \ |
| 45 | (offsetof(struct trace_probe, args) + \ | 50 | (offsetof(struct trace_probe, args) + \ |
| 46 | (sizeof(struct probe_arg) * (n))) | 51 | (sizeof(struct probe_arg) * (n))) |
| @@ -90,7 +95,7 @@ static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp) | |||
| 90 | } | 95 | } |
| 91 | 96 | ||
| 92 | static int register_probe_event(struct trace_probe *tp); | 97 | static int register_probe_event(struct trace_probe *tp); |
| 93 | static void unregister_probe_event(struct trace_probe *tp); | 98 | static int unregister_probe_event(struct trace_probe *tp); |
| 94 | 99 | ||
| 95 | static DEFINE_MUTEX(probe_lock); | 100 | static DEFINE_MUTEX(probe_lock); |
| 96 | static LIST_HEAD(probe_list); | 101 | static LIST_HEAD(probe_list); |
| @@ -150,6 +155,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 150 | goto error; | 155 | goto error; |
| 151 | 156 | ||
| 152 | INIT_LIST_HEAD(&tp->list); | 157 | INIT_LIST_HEAD(&tp->list); |
| 158 | INIT_LIST_HEAD(&tp->files); | ||
| 153 | return tp; | 159 | return tp; |
| 154 | error: | 160 | error: |
| 155 | kfree(tp->call.name); | 161 | kfree(tp->call.name); |
| @@ -183,25 +189,6 @@ static struct trace_probe *find_trace_probe(const char *event, | |||
| 183 | return NULL; | 189 | return NULL; |
| 184 | } | 190 | } |
| 185 | 191 | ||
| 186 | static int trace_probe_nr_files(struct trace_probe *tp) | ||
| 187 | { | ||
| 188 | struct ftrace_event_file **file; | ||
| 189 | int ret = 0; | ||
| 190 | |||
| 191 | /* | ||
| 192 | * Since all tp->files updater is protected by probe_enable_lock, | ||
| 193 | * we don't need to lock an rcu_read_lock. | ||
| 194 | */ | ||
| 195 | file = rcu_dereference_raw(tp->files); | ||
| 196 | if (file) | ||
| 197 | while (*(file++)) | ||
| 198 | ret++; | ||
| 199 | |||
| 200 | return ret; | ||
| 201 | } | ||
| 202 | |||
| 203 | static DEFINE_MUTEX(probe_enable_lock); | ||
| 204 | |||
| 205 | /* | 192 | /* |
| 206 | * Enable trace_probe | 193 | * Enable trace_probe |
| 207 | * if the file is NULL, enable "perf" handler, or enable "trace" handler. | 194 | * if the file is NULL, enable "perf" handler, or enable "trace" handler. |
| @@ -211,67 +198,42 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
| 211 | { | 198 | { |
| 212 | int ret = 0; | 199 | int ret = 0; |
| 213 | 200 | ||
| 214 | mutex_lock(&probe_enable_lock); | ||
| 215 | |||
| 216 | if (file) { | 201 | if (file) { |
| 217 | struct ftrace_event_file **new, **old; | 202 | struct event_file_link *link; |
| 218 | int n = trace_probe_nr_files(tp); | 203 | |
| 219 | 204 | link = kmalloc(sizeof(*link), GFP_KERNEL); | |
| 220 | old = rcu_dereference_raw(tp->files); | 205 | if (!link) { |
| 221 | /* 1 is for new one and 1 is for stopper */ | ||
| 222 | new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *), | ||
| 223 | GFP_KERNEL); | ||
| 224 | if (!new) { | ||
| 225 | ret = -ENOMEM; | 206 | ret = -ENOMEM; |
| 226 | goto out_unlock; | 207 | goto out; |
| 227 | } | 208 | } |
| 228 | memcpy(new, old, n * sizeof(struct ftrace_event_file *)); | ||
| 229 | new[n] = file; | ||
| 230 | /* The last one keeps a NULL */ | ||
| 231 | 209 | ||
| 232 | rcu_assign_pointer(tp->files, new); | 210 | link->file = file; |
| 233 | tp->flags |= TP_FLAG_TRACE; | 211 | list_add_tail_rcu(&link->list, &tp->files); |
| 234 | 212 | ||
| 235 | if (old) { | 213 | tp->flags |= TP_FLAG_TRACE; |
| 236 | /* Make sure the probe is done with old files */ | ||
| 237 | synchronize_sched(); | ||
| 238 | kfree(old); | ||
| 239 | } | ||
| 240 | } else | 214 | } else |
| 241 | tp->flags |= TP_FLAG_PROFILE; | 215 | tp->flags |= TP_FLAG_PROFILE; |
| 242 | 216 | ||
| 243 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && | 217 | if (trace_probe_is_registered(tp) && !trace_probe_has_gone(tp)) { |
| 244 | !trace_probe_has_gone(tp)) { | ||
| 245 | if (trace_probe_is_return(tp)) | 218 | if (trace_probe_is_return(tp)) |
| 246 | ret = enable_kretprobe(&tp->rp); | 219 | ret = enable_kretprobe(&tp->rp); |
| 247 | else | 220 | else |
| 248 | ret = enable_kprobe(&tp->rp.kp); | 221 | ret = enable_kprobe(&tp->rp.kp); |
| 249 | } | 222 | } |
| 250 | 223 | out: | |
| 251 | out_unlock: | ||
| 252 | mutex_unlock(&probe_enable_lock); | ||
| 253 | |||
| 254 | return ret; | 224 | return ret; |
| 255 | } | 225 | } |
| 256 | 226 | ||
| 257 | static int | 227 | static struct event_file_link * |
| 258 | trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) | 228 | find_event_file_link(struct trace_probe *tp, struct ftrace_event_file *file) |
| 259 | { | 229 | { |
| 260 | struct ftrace_event_file **files; | 230 | struct event_file_link *link; |
| 261 | int i; | ||
| 262 | 231 | ||
| 263 | /* | 232 | list_for_each_entry(link, &tp->files, list) |
| 264 | * Since all tp->files updater is protected by probe_enable_lock, | 233 | if (link->file == file) |
| 265 | * we don't need to lock an rcu_read_lock. | 234 | return link; |
| 266 | */ | ||
| 267 | files = rcu_dereference_raw(tp->files); | ||
| 268 | if (files) { | ||
| 269 | for (i = 0; files[i]; i++) | ||
| 270 | if (files[i] == file) | ||
| 271 | return i; | ||
| 272 | } | ||
| 273 | 235 | ||
| 274 | return -1; | 236 | return NULL; |
| 275 | } | 237 | } |
| 276 | 238 | ||
| 277 | /* | 239 | /* |
| @@ -281,43 +243,23 @@ trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) | |||
| 281 | static int | 243 | static int |
| 282 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | 244 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) |
| 283 | { | 245 | { |
| 246 | struct event_file_link *link = NULL; | ||
| 247 | int wait = 0; | ||
| 284 | int ret = 0; | 248 | int ret = 0; |
| 285 | 249 | ||
| 286 | mutex_lock(&probe_enable_lock); | ||
| 287 | |||
| 288 | if (file) { | 250 | if (file) { |
| 289 | struct ftrace_event_file **new, **old; | 251 | link = find_event_file_link(tp, file); |
| 290 | int n = trace_probe_nr_files(tp); | 252 | if (!link) { |
| 291 | int i, j; | ||
| 292 | |||
| 293 | old = rcu_dereference_raw(tp->files); | ||
| 294 | if (n == 0 || trace_probe_file_index(tp, file) < 0) { | ||
| 295 | ret = -EINVAL; | 253 | ret = -EINVAL; |
| 296 | goto out_unlock; | 254 | goto out; |
| 297 | } | 255 | } |
| 298 | 256 | ||
| 299 | if (n == 1) { /* Remove the last file */ | 257 | list_del_rcu(&link->list); |
| 300 | tp->flags &= ~TP_FLAG_TRACE; | 258 | wait = 1; |
| 301 | new = NULL; | 259 | if (!list_empty(&tp->files)) |
| 302 | } else { | 260 | goto out; |
| 303 | new = kzalloc(n * sizeof(struct ftrace_event_file *), | ||
| 304 | GFP_KERNEL); | ||
| 305 | if (!new) { | ||
| 306 | ret = -ENOMEM; | ||
| 307 | goto out_unlock; | ||
| 308 | } | ||
| 309 | |||
| 310 | /* This copy & check loop copies the NULL stopper too */ | ||
| 311 | for (i = 0, j = 0; j < n && i < n + 1; i++) | ||
| 312 | if (old[i] != file) | ||
| 313 | new[j++] = old[i]; | ||
| 314 | } | ||
| 315 | |||
| 316 | rcu_assign_pointer(tp->files, new); | ||
| 317 | 261 | ||
| 318 | /* Make sure the probe is done with old files */ | 262 | tp->flags &= ~TP_FLAG_TRACE; |
| 319 | synchronize_sched(); | ||
| 320 | kfree(old); | ||
| 321 | } else | 263 | } else |
| 322 | tp->flags &= ~TP_FLAG_PROFILE; | 264 | tp->flags &= ~TP_FLAG_PROFILE; |
| 323 | 265 | ||
| @@ -326,10 +268,21 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | |||
| 326 | disable_kretprobe(&tp->rp); | 268 | disable_kretprobe(&tp->rp); |
| 327 | else | 269 | else |
| 328 | disable_kprobe(&tp->rp.kp); | 270 | disable_kprobe(&tp->rp.kp); |
| 271 | wait = 1; | ||
| 272 | } | ||
| 273 | out: | ||
| 274 | if (wait) { | ||
| 275 | /* | ||
| 276 | * Synchronize with kprobe_trace_func/kretprobe_trace_func | ||
| 277 | * to ensure disabled (all running handlers are finished). | ||
| 278 | * This is not only for kfree(), but also the caller, | ||
| 279 | * trace_remove_event_call() supposes it for releasing | ||
| 280 | * event_call related objects, which will be accessed in | ||
| 281 | * the kprobe_trace_func/kretprobe_trace_func. | ||
| 282 | */ | ||
| 283 | synchronize_sched(); | ||
| 284 | kfree(link); /* Ignored if link == NULL */ | ||
| 329 | } | 285 | } |
| 330 | |||
| 331 | out_unlock: | ||
| 332 | mutex_unlock(&probe_enable_lock); | ||
| 333 | 286 | ||
| 334 | return ret; | 287 | return ret; |
| 335 | } | 288 | } |
| @@ -398,9 +351,12 @@ static int unregister_trace_probe(struct trace_probe *tp) | |||
| 398 | if (trace_probe_is_enabled(tp)) | 351 | if (trace_probe_is_enabled(tp)) |
| 399 | return -EBUSY; | 352 | return -EBUSY; |
| 400 | 353 | ||
| 354 | /* Will fail if probe is being used by ftrace or perf */ | ||
| 355 | if (unregister_probe_event(tp)) | ||
| 356 | return -EBUSY; | ||
| 357 | |||
| 401 | __unregister_trace_probe(tp); | 358 | __unregister_trace_probe(tp); |
| 402 | list_del(&tp->list); | 359 | list_del(&tp->list); |
| 403 | unregister_probe_event(tp); | ||
| 404 | 360 | ||
| 405 | return 0; | 361 | return 0; |
| 406 | } | 362 | } |
| @@ -679,7 +635,9 @@ static int release_all_trace_probes(void) | |||
| 679 | /* TODO: Use batch unregistration */ | 635 | /* TODO: Use batch unregistration */ |
| 680 | while (!list_empty(&probe_list)) { | 636 | while (!list_empty(&probe_list)) { |
| 681 | tp = list_entry(probe_list.next, struct trace_probe, list); | 637 | tp = list_entry(probe_list.next, struct trace_probe, list); |
| 682 | unregister_trace_probe(tp); | 638 | ret = unregister_trace_probe(tp); |
| 639 | if (ret) | ||
| 640 | goto end; | ||
| 683 | free_trace_probe(tp); | 641 | free_trace_probe(tp); |
| 684 | } | 642 | } |
| 685 | 643 | ||
| @@ -885,20 +843,10 @@ __kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs, | |||
| 885 | static __kprobes void | 843 | static __kprobes void |
| 886 | kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) | 844 | kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) |
| 887 | { | 845 | { |
| 888 | /* | 846 | struct event_file_link *link; |
| 889 | * Note: preempt is already disabled around the kprobe handler. | ||
| 890 | * However, we still need an smp_read_barrier_depends() corresponding | ||
| 891 | * to smp_wmb() in rcu_assign_pointer() to access the pointer. | ||
| 892 | */ | ||
| 893 | struct ftrace_event_file **file = rcu_dereference_raw(tp->files); | ||
| 894 | |||
| 895 | if (unlikely(!file)) | ||
| 896 | return; | ||
| 897 | 847 | ||
| 898 | while (*file) { | 848 | list_for_each_entry_rcu(link, &tp->files, list) |
| 899 | __kprobe_trace_func(tp, regs, *file); | 849 | __kprobe_trace_func(tp, regs, link->file); |
| 900 | file++; | ||
| 901 | } | ||
| 902 | } | 850 | } |
| 903 | 851 | ||
| 904 | /* Kretprobe handler */ | 852 | /* Kretprobe handler */ |
| @@ -945,20 +893,10 @@ static __kprobes void | |||
| 945 | kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, | 893 | kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
| 946 | struct pt_regs *regs) | 894 | struct pt_regs *regs) |
| 947 | { | 895 | { |
| 948 | /* | 896 | struct event_file_link *link; |
| 949 | * Note: preempt is already disabled around the kprobe handler. | ||
| 950 | * However, we still need an smp_read_barrier_depends() corresponding | ||
| 951 | * to smp_wmb() in rcu_assign_pointer() to access the pointer. | ||
| 952 | */ | ||
| 953 | struct ftrace_event_file **file = rcu_dereference_raw(tp->files); | ||
| 954 | |||
| 955 | if (unlikely(!file)) | ||
| 956 | return; | ||
| 957 | 897 | ||
| 958 | while (*file) { | 898 | list_for_each_entry_rcu(link, &tp->files, list) |
| 959 | __kretprobe_trace_func(tp, ri, regs, *file); | 899 | __kretprobe_trace_func(tp, ri, regs, link->file); |
| 960 | file++; | ||
| 961 | } | ||
| 962 | } | 900 | } |
| 963 | 901 | ||
| 964 | /* Event entry printers */ | 902 | /* Event entry printers */ |
| @@ -1157,13 +1095,14 @@ kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) | |||
| 1157 | int size, __size, dsize; | 1095 | int size, __size, dsize; |
| 1158 | int rctx; | 1096 | int rctx; |
| 1159 | 1097 | ||
| 1098 | head = this_cpu_ptr(call->perf_events); | ||
| 1099 | if (hlist_empty(head)) | ||
| 1100 | return; | ||
| 1101 | |||
| 1160 | dsize = __get_data_size(tp, regs); | 1102 | dsize = __get_data_size(tp, regs); |
| 1161 | __size = sizeof(*entry) + tp->size + dsize; | 1103 | __size = sizeof(*entry) + tp->size + dsize; |
| 1162 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1104 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
| 1163 | size -= sizeof(u32); | 1105 | size -= sizeof(u32); |
| 1164 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | ||
| 1165 | "profile buffer not large enough")) | ||
| 1166 | return; | ||
| 1167 | 1106 | ||
| 1168 | entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); | 1107 | entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); |
| 1169 | if (!entry) | 1108 | if (!entry) |
| @@ -1172,10 +1111,7 @@ kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) | |||
| 1172 | entry->ip = (unsigned long)tp->rp.kp.addr; | 1111 | entry->ip = (unsigned long)tp->rp.kp.addr; |
| 1173 | memset(&entry[1], 0, dsize); | 1112 | memset(&entry[1], 0, dsize); |
| 1174 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 1113 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
| 1175 | 1114 | perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); | |
| 1176 | head = this_cpu_ptr(call->perf_events); | ||
| 1177 | perf_trace_buf_submit(entry, size, rctx, | ||
| 1178 | entry->ip, 1, regs, head, NULL); | ||
| 1179 | } | 1115 | } |
| 1180 | 1116 | ||
| 1181 | /* Kretprobe profile handler */ | 1117 | /* Kretprobe profile handler */ |
| @@ -1189,13 +1125,14 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, | |||
| 1189 | int size, __size, dsize; | 1125 | int size, __size, dsize; |
| 1190 | int rctx; | 1126 | int rctx; |
| 1191 | 1127 | ||
| 1128 | head = this_cpu_ptr(call->perf_events); | ||
| 1129 | if (hlist_empty(head)) | ||
| 1130 | return; | ||
| 1131 | |||
| 1192 | dsize = __get_data_size(tp, regs); | 1132 | dsize = __get_data_size(tp, regs); |
| 1193 | __size = sizeof(*entry) + tp->size + dsize; | 1133 | __size = sizeof(*entry) + tp->size + dsize; |
| 1194 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1134 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
| 1195 | size -= sizeof(u32); | 1135 | size -= sizeof(u32); |
| 1196 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, | ||
| 1197 | "profile buffer not large enough")) | ||
| 1198 | return; | ||
| 1199 | 1136 | ||
| 1200 | entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); | 1137 | entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx); |
| 1201 | if (!entry) | 1138 | if (!entry) |
| @@ -1204,13 +1141,16 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, | |||
| 1204 | entry->func = (unsigned long)tp->rp.kp.addr; | 1141 | entry->func = (unsigned long)tp->rp.kp.addr; |
| 1205 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1142 | entry->ret_ip = (unsigned long)ri->ret_addr; |
| 1206 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 1143 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
| 1207 | 1144 | perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); | |
| 1208 | head = this_cpu_ptr(call->perf_events); | ||
| 1209 | perf_trace_buf_submit(entry, size, rctx, | ||
| 1210 | entry->ret_ip, 1, regs, head, NULL); | ||
| 1211 | } | 1145 | } |
| 1212 | #endif /* CONFIG_PERF_EVENTS */ | 1146 | #endif /* CONFIG_PERF_EVENTS */ |
| 1213 | 1147 | ||
| 1148 | /* | ||
| 1149 | * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. | ||
| 1150 | * | ||
| 1151 | * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe | ||
| 1152 | * lockless, but we can't race with this __init function. | ||
| 1153 | */ | ||
| 1214 | static __kprobes | 1154 | static __kprobes |
| 1215 | int kprobe_register(struct ftrace_event_call *event, | 1155 | int kprobe_register(struct ftrace_event_call *event, |
| 1216 | enum trace_reg type, void *data) | 1156 | enum trace_reg type, void *data) |
| @@ -1312,11 +1252,15 @@ static int register_probe_event(struct trace_probe *tp) | |||
| 1312 | return ret; | 1252 | return ret; |
| 1313 | } | 1253 | } |
| 1314 | 1254 | ||
| 1315 | static void unregister_probe_event(struct trace_probe *tp) | 1255 | static int unregister_probe_event(struct trace_probe *tp) |
| 1316 | { | 1256 | { |
| 1257 | int ret; | ||
| 1258 | |||
| 1317 | /* tp->event is unregistered in trace_remove_event_call() */ | 1259 | /* tp->event is unregistered in trace_remove_event_call() */ |
| 1318 | trace_remove_event_call(&tp->call); | 1260 | ret = trace_remove_event_call(&tp->call); |
| 1319 | kfree(tp->call.print_fmt); | 1261 | if (!ret) |
| 1262 | kfree(tp->call.print_fmt); | ||
| 1263 | return ret; | ||
| 1320 | } | 1264 | } |
| 1321 | 1265 | ||
| 1322 | /* Make a debugfs interface for controlling probe points */ | 1266 | /* Make a debugfs interface for controlling probe points */ |
| @@ -1376,6 +1320,10 @@ find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr) | |||
| 1376 | return NULL; | 1320 | return NULL; |
| 1377 | } | 1321 | } |
| 1378 | 1322 | ||
| 1323 | /* | ||
| 1324 | * Nobody but us can call enable_trace_probe/disable_trace_probe at this | ||
| 1325 | * stage, we can do this lockless. | ||
| 1326 | */ | ||
| 1379 | static __init int kprobe_trace_self_tests_init(void) | 1327 | static __init int kprobe_trace_self_tests_init(void) |
| 1380 | { | 1328 | { |
| 1381 | int ret, warn = 0; | 1329 | int ret, warn = 0; |
