event-rule: introduce event-rule kprobe
[lttng-tools.git] / src / common / event-rule / kprobe.c
1 /*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <assert.h>
9 #include <common/error.h>
10 #include <common/macros.h>
11 #include <common/payload.h>
12 #include <common/payload-view.h>
13 #include <common/runas.h>
14 #include <ctype.h>
15 #include <lttng/constant.h>
16 #include <lttng/event-rule/event-rule-internal.h>
17 #include <lttng/event-rule/kprobe-internal.h>
18 #include <lttng/kernel-probe.h>
19 #include <lttng/kernel-probe-internal.h>
20 #include <stdio.h>
21
22 #define IS_KPROBE_EVENT_RULE(rule) \
23 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KPROBE)
24
25 #if (LTTNG_SYMBOL_NAME_LEN == 256)
26 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
27 #endif
28
29 static void lttng_event_rule_kprobe_destroy(struct lttng_event_rule *rule)
30 {
31 struct lttng_event_rule_kprobe *kprobe;
32
33 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
34
35 lttng_kernel_probe_location_destroy(kprobe->location);
36 free(kprobe->name);
37 free(kprobe);
38 }
39
40 static bool lttng_event_rule_kprobe_validate(
41 const struct lttng_event_rule *rule)
42 {
43 bool valid = false;
44 struct lttng_event_rule_kprobe *kprobe;
45
46 if (!rule) {
47 goto end;
48 }
49
50 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
51
52 /* Required field. */
53 if (!kprobe->name) {
54 ERR("Invalid name event rule: a name must be set.");
55 goto end;
56 }
57
58 /* Required field. */
59 if(!kprobe->location) {
60 ERR("Invalid name event rule: a location must be set.");
61 goto end;
62 }
63
64 valid = true;
65 end:
66 return valid;
67 }
68
69 static int lttng_event_rule_kprobe_serialize(
70 const struct lttng_event_rule *rule,
71 struct lttng_payload *payload)
72 {
73 int ret;
74 size_t name_len, header_offset, size_before_location;
75 struct lttng_event_rule_kprobe *kprobe;
76 struct lttng_event_rule_kprobe_comm kprobe_comm;
77 struct lttng_event_rule_kprobe_comm *header;
78
79 if (!rule || !IS_KPROBE_EVENT_RULE(rule)) {
80 ret = -1;
81 goto end;
82 }
83
84 header_offset = payload->buffer.size;
85
86 DBG("Serializing kprobe event rule.");
87 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
88
89 name_len = strlen(kprobe->name) + 1;
90 kprobe_comm.name_len = name_len;
91
92 ret = lttng_dynamic_buffer_append(
93 &payload->buffer, &kprobe_comm, sizeof(kprobe_comm));
94 if (ret) {
95 goto end;
96 }
97
98 ret = lttng_dynamic_buffer_append(&payload->buffer, kprobe->name, name_len);
99 if (ret) {
100 goto end;
101 }
102
103 size_before_location = payload->buffer.size;
104
105 ret = lttng_kernel_probe_location_serialize(kprobe->location, payload);
106 if (ret < 0) {
107 goto end;
108 }
109
110 /* Update the header regarding the probe size. */
111 header = (struct lttng_event_rule_kprobe_comm*) (
112 (char *) payload->buffer.data + header_offset);
113 header->location_len = payload->buffer.size - size_before_location;
114
115 ret = 0;
116
117 end:
118 return ret;
119 }
120
121 static bool lttng_event_rule_kprobe_is_equal(const struct lttng_event_rule *_a,
122 const struct lttng_event_rule *_b)
123 {
124 bool is_equal = false;
125 struct lttng_event_rule_kprobe *a, *b;
126
127 a = container_of(_a, struct lttng_event_rule_kprobe, parent);
128 b = container_of(_b, struct lttng_event_rule_kprobe, parent);
129
130 /* Quick checks */
131 if (!!a->name != !!b->name) {
132 goto end;
133 }
134
135 /* Long check */
136 assert(a->name);
137 assert(b->name);
138 if (strcmp(a->name, b->name)) {
139 goto end;
140 }
141
142 is_equal = lttng_kernel_probe_location_is_equal(
143 a->location, b->location);
144 end:
145 return is_equal;
146 }
147
148 static enum lttng_error_code lttng_event_rule_kprobe_generate_filter_bytecode(
149 struct lttng_event_rule *rule, uid_t uid, gid_t gid)
150 {
151 /* Nothing to do. */
152 return LTTNG_OK;
153 }
154
155 static const char *lttng_event_rule_kprobe_get_filter(
156 const struct lttng_event_rule *rule)
157 {
158 /* Not supported. */
159 return NULL;
160 }
161
162 static const struct lttng_filter_bytecode *
163 lttng_event_rule_kprobe_get_filter_bytecode(const struct lttng_event_rule *rule)
164 {
165 /* Not supported. */
166 return NULL;
167 }
168
169 static struct lttng_event_exclusion *
170 lttng_event_rule_kprobe_generate_exclusions(const struct lttng_event_rule *rule)
171 {
172 /* Not supported. */
173 return NULL;
174 }
175
176 struct lttng_event_rule *lttng_event_rule_kprobe_create()
177 {
178 struct lttng_event_rule *rule = NULL;
179 struct lttng_event_rule_kprobe *krule;
180
181 krule = zmalloc(sizeof(struct lttng_event_rule_kprobe));
182 if (!krule) {
183 goto end;
184 }
185
186 rule = &krule->parent;
187 lttng_event_rule_init(&krule->parent, LTTNG_EVENT_RULE_TYPE_KPROBE);
188 krule->parent.validate = lttng_event_rule_kprobe_validate;
189 krule->parent.serialize = lttng_event_rule_kprobe_serialize;
190 krule->parent.equal = lttng_event_rule_kprobe_is_equal;
191 krule->parent.destroy = lttng_event_rule_kprobe_destroy;
192 krule->parent.generate_filter_bytecode =
193 lttng_event_rule_kprobe_generate_filter_bytecode;
194 krule->parent.get_filter = lttng_event_rule_kprobe_get_filter;
195 krule->parent.get_filter_bytecode =
196 lttng_event_rule_kprobe_get_filter_bytecode;
197 krule->parent.generate_exclusions =
198 lttng_event_rule_kprobe_generate_exclusions;
199 end:
200 return rule;
201 }
202
203 LTTNG_HIDDEN
204 ssize_t lttng_event_rule_kprobe_create_from_payload(
205 struct lttng_payload_view *view,
206 struct lttng_event_rule **_event_rule)
207 {
208 ssize_t ret, offset = 0;
209 enum lttng_event_rule_status status;
210 const struct lttng_event_rule_kprobe_comm *kprobe_comm;
211 const char *name;
212 struct lttng_buffer_view current_buffer_view;
213 struct lttng_event_rule *rule = NULL;
214 struct lttng_event_rule_kprobe *kprobe = NULL;
215 struct lttng_kernel_probe_location *location;
216
217 if (!_event_rule) {
218 ret = -1;
219 goto end;
220 }
221
222 if (view->buffer.size < sizeof(*kprobe_comm)) {
223 ERR("Failed to initialize from malformed event rule kprobe: buffer too short to contain header.");
224 ret = -1;
225 goto end;
226 }
227
228 current_buffer_view = lttng_buffer_view_from_view(
229 &view->buffer, offset, sizeof(*kprobe_comm));
230 kprobe_comm = (typeof(kprobe_comm)) current_buffer_view.data;
231 if (!kprobe_comm) {
232 ret = -1;
233 goto end;
234 }
235
236 rule = lttng_event_rule_kprobe_create();
237 if (!rule) {
238 ERR("Failed to create event rule kprobe.");
239 ret = -1;
240 goto end;
241 }
242
243 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
244
245 /* Skip to payload */
246 offset += current_buffer_view.size;
247
248 {
249 /* Map the name. */
250 struct lttng_payload_view current_payload_view =
251 lttng_payload_view_from_view(view, offset,
252 kprobe_comm->name_len);
253
254 name = current_payload_view.buffer.data;
255 if (!name) {
256 ret = -1;
257 goto end;
258 }
259
260 if (!lttng_buffer_view_contains_string(
261 &current_payload_view.buffer, name,
262 kprobe_comm->name_len)) {
263 ret = -1;
264 goto end;
265 }
266 }
267
268 /* Skip after the name. */
269 offset += kprobe_comm->name_len;
270
271 /* Map the kernel probe location. */
272 {
273 struct lttng_payload_view current_payload_view =
274 lttng_payload_view_from_view(view, offset,
275 kprobe_comm->location_len);
276
277 ret = lttng_kernel_probe_location_create_from_payload(
278 &current_payload_view, &location);
279 if (ret < 0) {
280 ret = -1;
281 goto end;
282 }
283 }
284
285 if (ret != kprobe_comm->location_len) {
286 ret = -1;
287 goto end;
288 }
289
290 kprobe->location = location;
291
292 /* Skip after the location */
293 offset += kprobe_comm->location_len;
294
295 status = lttng_event_rule_kprobe_set_name(rule, name);
296 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
297 ERR("Failed to set event rule kprobe name.");
298 ret = -1;
299 goto end;
300 }
301
302 *_event_rule = rule;
303 rule = NULL;
304 ret = offset;
305 end:
306 lttng_event_rule_destroy(rule);
307 return ret;
308 }
309
310 enum lttng_event_rule_status lttng_event_rule_kprobe_set_location(
311 struct lttng_event_rule *rule,
312 const struct lttng_kernel_probe_location *location)
313 {
314 struct lttng_kernel_probe_location *location_copy = NULL;
315 struct lttng_event_rule_kprobe *kprobe;
316 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
317
318 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !location) {
319 status = LTTNG_EVENT_RULE_STATUS_INVALID;
320 goto end;
321 }
322
323 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
324 location_copy = lttng_kernel_probe_location_copy(location);
325 if (!location_copy) {
326 status = LTTNG_EVENT_RULE_STATUS_ERROR;
327 goto end;
328 }
329
330 if (kprobe->location) {
331 lttng_kernel_probe_location_destroy(kprobe->location);
332 }
333
334 kprobe->location = location_copy;
335 location_copy = NULL;
336 end:
337 lttng_kernel_probe_location_destroy(location_copy);
338 return status;
339 }
340
341 enum lttng_event_rule_status lttng_event_rule_kprobe_get_location(
342 const struct lttng_event_rule *rule,
343 const struct lttng_kernel_probe_location **location)
344 {
345 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
346 struct lttng_event_rule_kprobe *kprobe;
347
348 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !location) {
349 status = LTTNG_EVENT_RULE_STATUS_INVALID;
350 goto end;
351 }
352
353 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
354 *location = kprobe->location;
355
356 if (!*location) {
357 status = LTTNG_EVENT_RULE_STATUS_UNSET;
358 goto end;
359 }
360
361 end:
362 return status;
363 }
364
365 enum lttng_event_rule_status lttng_event_rule_kprobe_set_name(
366 struct lttng_event_rule *rule, const char *name)
367 {
368 char *name_copy = NULL;
369 struct lttng_event_rule_kprobe *kprobe;
370 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
371
372 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name ||
373 strlen(name) == 0) {
374 status = LTTNG_EVENT_RULE_STATUS_INVALID;
375 goto end;
376 }
377
378 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
379 name_copy = strdup(name);
380 if (!name_copy) {
381 status = LTTNG_EVENT_RULE_STATUS_ERROR;
382 goto end;
383 }
384
385 free(kprobe->name);
386
387 kprobe->name = name_copy;
388 name_copy = NULL;
389 end:
390 return status;
391 }
392
393 enum lttng_event_rule_status lttng_event_rule_kprobe_get_name(
394 const struct lttng_event_rule *rule, const char **name)
395 {
396 struct lttng_event_rule_kprobe *kprobe;
397 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
398
399 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name) {
400 status = LTTNG_EVENT_RULE_STATUS_INVALID;
401 goto end;
402 }
403
404 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
405 if (!kprobe->name) {
406 status = LTTNG_EVENT_RULE_STATUS_UNSET;
407 goto end;
408 }
409
410 *name = kprobe->name;
411 end:
412 return status;
413 }
This page took 0.037395 seconds and 5 git commands to generate.