SoW-2020-0003: Trace Hit Counters
[deliverable/lttng-modules.git] / src / probes / lttng-uprobes.c
1 /* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only)
2 *
3 * probes/lttng-uprobes.c
4 *
5 * LTTng uprobes integration module.
6 *
7 * Copyright (C) 2013 Yannick Brosseau <yannick.brosseau@gmail.com>
8 * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 *
10 */
11
12 #include <wrapper/fdtable.h>
13 #include <linux/list.h>
14 #include <linux/module.h>
15 #include <linux/namei.h>
16 #include <linux/slab.h>
17 #include <linux/uaccess.h>
18 #include <lttng/events.h>
19 #include <lttng/tracer.h>
20 #include <wrapper/irqflags.h>
21 #include <ringbuffer/frontend_types.h>
22 #include <wrapper/uprobes.h>
23 #include <wrapper/vmalloc.h>
24
25 static
26 int lttng_uprobes_event_handler_pre(struct uprobe_consumer *uc, struct pt_regs *regs)
27 {
28 struct lttng_uprobe_handler *uprobe_handler =
29 container_of(uc, struct lttng_uprobe_handler, up_consumer);
30 struct lttng_event *event = uprobe_handler->u.event;
31 struct lttng_probe_ctx lttng_probe_ctx = {
32 .event = event,
33 .interruptible = !lttng_regs_irqs_disabled(regs),
34 };
35 struct lttng_event_container *container = event->container;
36 int ret;
37
38 struct {
39 unsigned long ip;
40 } payload;
41
42 if (unlikely(!LTTNG_READ_ONCE(container->session->active)))
43 return 0;
44 if (unlikely(!LTTNG_READ_ONCE(container->enabled)))
45 return 0;
46 if (unlikely(!LTTNG_READ_ONCE(event->enabled)))
47 return 0;
48
49 switch (container->type) {
50 case LTTNG_EVENT_CONTAINER_CHANNEL:
51 {
52 struct lttng_channel *chan = lttng_event_container_get_channel(container);
53 struct lib_ring_buffer_ctx ctx;
54
55 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx,
56 sizeof(payload), lttng_alignof(payload), -1);
57
58 ret = chan->ops->event_reserve(&ctx, event->id);
59 if (ret < 0)
60 return 0;
61
62 /* Event payload. */
63 payload.ip = (unsigned long)instruction_pointer(regs);
64
65 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload));
66 chan->ops->event_write(&ctx, &payload, sizeof(payload));
67 chan->ops->event_commit(&ctx);
68 break;
69 }
70 case LTTNG_EVENT_CONTAINER_COUNTER:
71 {
72 struct lttng_counter *counter = lttng_event_container_get_counter(container);
73 size_t index = event->id;
74
75 (void) counter->ops->counter_add(counter->counter, &index, 1);
76 break;
77 }
78 }
79 return 0;
80 }
81
82 static
83 int lttng_uprobes_event_notifier_handler_pre(struct uprobe_consumer *uc, struct pt_regs *regs)
84 {
85 struct lttng_uprobe_handler *uprobe_handler =
86 container_of(uc, struct lttng_uprobe_handler, up_consumer);
87 struct lttng_event_notifier *event_notifier = uprobe_handler->u.event_notifier;
88 struct lttng_kernel_notifier_ctx notif_ctx;
89
90 if (unlikely(!READ_ONCE(event_notifier->enabled)))
91 return 0;
92
93 notif_ctx.eval_capture = LTTNG_READ_ONCE(event_notifier->eval_capture);
94 event_notifier->send_notification(event_notifier, NULL, NULL, &notif_ctx);
95 return 0;
96 }
97
98 /*
99 * Create event description.
100 */
101 static
102 int lttng_create_uprobe_event(const char *name, struct lttng_event *event)
103 {
104 struct lttng_event_desc *desc;
105 struct lttng_event_field *fields;
106 int ret;
107
108 desc = kzalloc(sizeof(*event->desc), GFP_KERNEL);
109 if (!desc)
110 return -ENOMEM;
111 desc->name = kstrdup(name, GFP_KERNEL);
112 if (!desc->name) {
113 ret = -ENOMEM;
114 goto error_str;
115 }
116
117 desc->nr_fields = 1;
118 desc->fields = fields =
119 kzalloc(1 * sizeof(struct lttng_event_field), GFP_KERNEL);
120
121 if (!desc->fields) {
122 ret = -ENOMEM;
123 goto error_fields;
124 }
125 fields[0].name = "ip";
126 fields[0].type.atype = atype_integer;
127 fields[0].type.u.integer.size = sizeof(unsigned long) * CHAR_BIT;
128 fields[0].type.u.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
129 fields[0].type.u.integer.signedness = lttng_is_signed_type(unsigned long);
130 fields[0].type.u.integer.reverse_byte_order = 0;
131 fields[0].type.u.integer.base = 16;
132 fields[0].type.u.integer.encoding = lttng_encode_none;
133
134 desc->owner = THIS_MODULE;
135 event->desc = desc;
136
137 return 0;
138
139 error_fields:
140 kfree(desc->name);
141 error_str:
142 kfree(desc);
143 return ret;
144 }
145
146 /*
147 * Create event_notifier description.
148 */
149 static
150 int lttng_create_uprobe_event_notifier(const char *name, struct lttng_event_notifier *event_notifier)
151 {
152 struct lttng_event_desc *desc;
153 int ret;
154
155 desc = kzalloc(sizeof(*event_notifier->desc), GFP_KERNEL);
156 if (!desc)
157 return -ENOMEM;
158 desc->name = kstrdup(name, GFP_KERNEL);
159 if (!desc->name) {
160 ret = -ENOMEM;
161 goto error_str;
162 }
163
164 desc->nr_fields = 0;
165
166 desc->owner = THIS_MODULE;
167 event_notifier->desc = desc;
168
169 return 0;
170
171 error_str:
172 kfree(desc);
173 return ret;
174 }
175
176 /*
177 * Returns the inode struct from the current task and an fd. The inode is
178 * grabbed by this function and must be put once we are done with it using
179 * iput().
180 */
181 static struct inode *get_inode_from_fd(int fd)
182 {
183 struct file *file;
184 struct inode *inode;
185
186 rcu_read_lock();
187 /*
188 * Returns the file backing the given fd. Needs to be done inside an RCU
189 * critical section.
190 */
191 file = lttng_lookup_fd_rcu(fd);
192 if (file == NULL) {
193 printk(KERN_WARNING "LTTng: Cannot access file backing the fd(%d)\n", fd);
194 inode = NULL;
195 goto error;
196 }
197
198 /* Grab a reference on the inode. */
199 inode = igrab(file->f_path.dentry->d_inode);
200 if (inode == NULL)
201 printk(KERN_WARNING "LTTng: Cannot grab a reference on the inode.\n");
202 error:
203 rcu_read_unlock();
204 return inode;
205 }
206
207
208 static
209 int lttng_uprobes_add_callsite(struct lttng_uprobe *uprobe,
210 struct lttng_kernel_event_callsite __user *callsite,
211 int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs),
212 void *priv_data)
213 {
214 int ret = 0;
215 struct lttng_uprobe_handler *uprobe_handler;
216
217 if (!priv_data) {
218 ret = -EINVAL;
219 goto end;
220 }
221
222 uprobe_handler = kzalloc(sizeof(struct lttng_uprobe_handler), GFP_KERNEL);
223 if (!uprobe_handler) {
224 printk(KERN_WARNING "LTTng: Error allocating uprobe_handler");
225 ret = -ENOMEM;
226 goto end;
227 }
228
229 /* Ensure the memory we just allocated don't event_notifier page faults. */
230 wrapper_vmalloc_sync_mappings();
231
232 uprobe_handler->u.event = priv_data;
233 uprobe_handler->up_consumer.handler = handler;
234
235 ret = copy_from_user(&uprobe_handler->offset, &callsite->u.uprobe.offset, sizeof(uint64_t));
236 if (ret) {
237 goto register_error;
238 }
239
240 ret = wrapper_uprobe_register(uprobe->inode,
241 uprobe_handler->offset, &uprobe_handler->up_consumer);
242 if (ret) {
243 printk(KERN_WARNING "LTTng: Error registering probe on inode %lu "
244 "and offset 0x%llx\n", uprobe->inode->i_ino,
245 uprobe_handler->offset);
246 ret = -1;
247 goto register_error;
248 }
249
250 list_add(&uprobe_handler->node, &uprobe->head);
251
252 return ret;
253
254 register_error:
255 kfree(uprobe_handler);
256 end:
257 return ret;
258 }
259
260 int lttng_uprobes_event_add_callsite(struct lttng_event *event,
261 struct lttng_kernel_event_callsite __user *callsite)
262 {
263 return lttng_uprobes_add_callsite(&event->u.uprobe, callsite,
264 lttng_uprobes_event_handler_pre, event);
265 }
266 EXPORT_SYMBOL_GPL(lttng_uprobes_event_add_callsite);
267
268 int lttng_uprobes_event_notifier_add_callsite(struct lttng_event_notifier *event_notifier,
269 struct lttng_kernel_event_callsite __user *callsite)
270 {
271 return lttng_uprobes_add_callsite(&event_notifier->u.uprobe, callsite,
272 lttng_uprobes_event_notifier_handler_pre, event_notifier);
273 }
274 EXPORT_SYMBOL_GPL(lttng_uprobes_event_notifier_add_callsite);
275
276 static
277 int lttng_uprobes_register(struct lttng_uprobe *uprobe, int fd)
278 {
279 int ret = 0;
280 struct inode *inode;
281
282 inode = get_inode_from_fd(fd);
283 if (!inode) {
284 printk(KERN_WARNING "LTTng: Cannot get inode from fd\n");
285 ret = -EBADF;
286 goto inode_error;
287 }
288 uprobe->inode = inode;
289 INIT_LIST_HEAD(&uprobe->head);
290
291 inode_error:
292 return ret;
293 }
294
295 int lttng_uprobes_register_event(const char *name, int fd, struct lttng_event *event)
296 {
297 int ret = 0;
298
299 ret = lttng_create_uprobe_event(name, event);
300 if (ret)
301 goto error;
302
303 ret = lttng_uprobes_register(&event->u.uprobe, fd);
304 if (ret)
305 goto register_error;
306
307 return 0;
308
309 register_error:
310 kfree(event->desc->name);
311 kfree(event->desc);
312 error:
313 return ret;
314 }
315 EXPORT_SYMBOL_GPL(lttng_uprobes_register_event);
316
317 int lttng_uprobes_register_event_notifier(const char *name, int fd,
318 struct lttng_event_notifier *event_notifier)
319 {
320 int ret = 0;
321
322 ret = lttng_create_uprobe_event_notifier(name, event_notifier);
323 if (ret)
324 goto error;
325
326 ret = lttng_uprobes_register(&event_notifier->u.uprobe, fd);
327 if (ret)
328 goto register_error;
329
330 return 0;
331
332 register_error:
333 kfree(event_notifier->desc->name);
334 kfree(event_notifier->desc);
335 error:
336 return ret;
337 }
338 EXPORT_SYMBOL_GPL(lttng_uprobes_register_event_notifier);
339
340 static
341 void lttng_uprobes_unregister(struct inode *inode, struct list_head *head)
342 {
343 struct lttng_uprobe_handler *iter, *tmp;
344
345 /*
346 * Iterate over the list of handler, remove each handler from the list
347 * and free the struct.
348 */
349 list_for_each_entry_safe(iter, tmp, head, node) {
350 wrapper_uprobe_unregister(inode, iter->offset, &iter->up_consumer);
351 list_del(&iter->node);
352 kfree(iter);
353 }
354
355 }
356
357 void lttng_uprobes_unregister_event(struct lttng_event *event)
358 {
359 lttng_uprobes_unregister(event->u.uprobe.inode, &event->u.uprobe.head);
360 }
361 EXPORT_SYMBOL_GPL(lttng_uprobes_unregister_event);
362
363 void lttng_uprobes_unregister_event_notifier(struct lttng_event_notifier *event_notifier)
364 {
365 lttng_uprobes_unregister(event_notifier->u.uprobe.inode, &event_notifier->u.uprobe.head);
366 }
367 EXPORT_SYMBOL_GPL(lttng_uprobes_unregister_event_notifier);
368
369 void lttng_uprobes_destroy_event_private(struct lttng_event *event)
370 {
371 iput(event->u.uprobe.inode);
372 kfree(event->desc->name);
373 kfree(event->desc);
374 }
375 EXPORT_SYMBOL_GPL(lttng_uprobes_destroy_event_private);
376
377 void lttng_uprobes_destroy_event_notifier_private(struct lttng_event_notifier *event_notifier)
378 {
379 iput(event_notifier->u.uprobe.inode);
380 kfree(event_notifier->desc->name);
381 kfree(event_notifier->desc);
382 }
383 EXPORT_SYMBOL_GPL(lttng_uprobes_destroy_event_notifier_private);
384
385 MODULE_LICENSE("GPL and additional rights");
386 MODULE_AUTHOR("Yannick Brosseau");
387 MODULE_DESCRIPTION("Linux Trace Toolkit Uprobes Support");
This page took 0.038786 seconds and 5 git commands to generate.