Fix: unchecked buffer size for communication header
[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 current_buffer_view = lttng_buffer_view_from_view(
223 &view->buffer, offset, sizeof(*kprobe_comm));
224 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
225 ERR("Failed to initialize from malformed event rule kprobe: buffer too short to contain header.");
226 ret = -1;
227 goto end;
228 }
229
230 kprobe_comm = (typeof(kprobe_comm)) current_buffer_view.data;
231
232 rule = lttng_event_rule_kprobe_create();
233 if (!rule) {
234 ERR("Failed to create event rule kprobe.");
235 ret = -1;
236 goto end;
237 }
238
239 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
240
241 /* Skip to payload */
242 offset += current_buffer_view.size;
243
244 {
245 /* Map the name. */
246 struct lttng_payload_view current_payload_view =
247 lttng_payload_view_from_view(view, offset,
248 kprobe_comm->name_len);
249
250 if (!lttng_payload_view_is_valid(&current_payload_view)) {
251 ret = -1;
252 goto end;
253 }
254
255 name = current_payload_view.buffer.data;
256 if (!lttng_buffer_view_contains_string(
257 &current_payload_view.buffer, name,
258 kprobe_comm->name_len)) {
259 ret = -1;
260 goto end;
261 }
262 }
263
264 /* Skip after the name. */
265 offset += kprobe_comm->name_len;
266
267 /* Map the kernel probe location. */
268 {
269 struct lttng_payload_view current_payload_view =
270 lttng_payload_view_from_view(view, offset,
271 kprobe_comm->location_len);
272
273 if (!lttng_payload_view_is_valid(&current_payload_view)) {
274 ret = -1;
275 goto end;
276 }
277
278 ret = lttng_kernel_probe_location_create_from_payload(
279 &current_payload_view, &location);
280 if (ret < 0) {
281 ret = -1;
282 goto end;
283 }
284 }
285
286 if (ret != kprobe_comm->location_len) {
287 ret = -1;
288 goto end;
289 }
290
291 kprobe->location = location;
292
293 /* Skip after the location */
294 offset += kprobe_comm->location_len;
295
296 status = lttng_event_rule_kprobe_set_name(rule, name);
297 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
298 ERR("Failed to set event rule kprobe name.");
299 ret = -1;
300 goto end;
301 }
302
303 *_event_rule = rule;
304 rule = NULL;
305 ret = offset;
306 end:
307 lttng_event_rule_destroy(rule);
308 return ret;
309 }
310
311 enum lttng_event_rule_status lttng_event_rule_kprobe_set_location(
312 struct lttng_event_rule *rule,
313 const struct lttng_kernel_probe_location *location)
314 {
315 struct lttng_kernel_probe_location *location_copy = NULL;
316 struct lttng_event_rule_kprobe *kprobe;
317 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
318
319 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !location) {
320 status = LTTNG_EVENT_RULE_STATUS_INVALID;
321 goto end;
322 }
323
324 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
325 location_copy = lttng_kernel_probe_location_copy(location);
326 if (!location_copy) {
327 status = LTTNG_EVENT_RULE_STATUS_ERROR;
328 goto end;
329 }
330
331 if (kprobe->location) {
332 lttng_kernel_probe_location_destroy(kprobe->location);
333 }
334
335 kprobe->location = location_copy;
336 location_copy = NULL;
337 end:
338 lttng_kernel_probe_location_destroy(location_copy);
339 return status;
340 }
341
342 enum lttng_event_rule_status lttng_event_rule_kprobe_get_location(
343 const struct lttng_event_rule *rule,
344 const struct lttng_kernel_probe_location **location)
345 {
346 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
347 struct lttng_event_rule_kprobe *kprobe;
348
349 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !location) {
350 status = LTTNG_EVENT_RULE_STATUS_INVALID;
351 goto end;
352 }
353
354 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
355 *location = kprobe->location;
356
357 if (!*location) {
358 status = LTTNG_EVENT_RULE_STATUS_UNSET;
359 goto end;
360 }
361
362 end:
363 return status;
364 }
365
366 enum lttng_event_rule_status lttng_event_rule_kprobe_set_name(
367 struct lttng_event_rule *rule, const char *name)
368 {
369 char *name_copy = NULL;
370 struct lttng_event_rule_kprobe *kprobe;
371 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
372
373 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name ||
374 strlen(name) == 0) {
375 status = LTTNG_EVENT_RULE_STATUS_INVALID;
376 goto end;
377 }
378
379 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
380 name_copy = strdup(name);
381 if (!name_copy) {
382 status = LTTNG_EVENT_RULE_STATUS_ERROR;
383 goto end;
384 }
385
386 free(kprobe->name);
387
388 kprobe->name = name_copy;
389 name_copy = NULL;
390 end:
391 return status;
392 }
393
394 enum lttng_event_rule_status lttng_event_rule_kprobe_get_name(
395 const struct lttng_event_rule *rule, const char **name)
396 {
397 struct lttng_event_rule_kprobe *kprobe;
398 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
399
400 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name) {
401 status = LTTNG_EVENT_RULE_STATUS_INVALID;
402 goto end;
403 }
404
405 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
406 if (!kprobe->name) {
407 status = LTTNG_EVENT_RULE_STATUS_UNSET;
408 goto end;
409 }
410
411 *name = kprobe->name;
412 end:
413 return status;
414 }
This page took 0.057705 seconds and 5 git commands to generate.