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