Fix: event notification capture error handling
[lttng-modules.git] / src / lttng-event-notifier-notification.c
CommitLineData
21f58fb7
FD
1/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * lttng-event-notifier-notification.c
4 *
5 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 */
7
42f3ef8c
FD
8#include <linux/bug.h>
9
10#include <lttng/lttng-bytecode.h>
21f58fb7 11#include <lttng/events.h>
42f3ef8c 12#include <lttng/msgpack.h>
21f58fb7 13#include <lttng/event-notifier-notification.h>
437d5aa5 14#include <lttng/events-internal.h>
11b589f6 15#include <lttng/probe-user.h>
6657edec 16#include <wrapper/barrier.h>
21f58fb7 17
99d223ad 18/*
e699ee6c
MD
19 * The capture buffer size needs to be below 1024 bytes to avoid the
20 * frame to be larger than the 1024 limit enforced by the kernel. If we
21 * ever need to increase it, we will need to use a memory allocation
22 * scheme which allows allocating temporary memory chunks from the
23 * instrumentation sites. This could be done by adapting lttng
24 * tp-mempool to become nmi-safe and lock-free.
99d223ad
FD
25 */
26#define CAPTURE_BUFFER_SIZE 512
27
28struct lttng_event_notifier_notification {
29 int notification_fd;
30 uint64_t event_notifier_token;
31 uint8_t capture_buf[CAPTURE_BUFFER_SIZE];
32 struct lttng_msgpack_writer writer;
33 bool has_captures;
34};
35
42f3ef8c
FD
36static
37int capture_enum(struct lttng_msgpack_writer *writer,
38 struct lttng_interpreter_output *output)
39{
40 int ret;
41
42 /*
43 * Enums are captured as a map containing 2 key-value pairs. Such as:
44 * - type: enum
45 * value: 177
46 */
47 ret = lttng_msgpack_begin_map(writer, 2);
48 if (ret) {
42f3ef8c
FD
49 goto end;
50 }
51
52 ret = lttng_msgpack_write_str(writer, "type");
53 if (ret) {
42f3ef8c
FD
54 goto end;
55 }
56
57 ret = lttng_msgpack_write_str(writer, "enum");
58 if (ret) {
42f3ef8c
FD
59 goto end;
60 }
61
62 ret = lttng_msgpack_write_str(writer, "value");
63 if (ret) {
42f3ef8c
FD
64 goto end;
65 }
66
67 switch (output->type) {
68 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
69 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
70 if (ret) {
42f3ef8c
FD
71 goto end;
72 }
73 break;
74 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
75 ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
76 if (ret) {
42f3ef8c
FD
77 goto end;
78 }
79 break;
80 default:
736f2dd6 81 WARN_ON_ONCE(1);
42f3ef8c
FD
82 }
83
84 ret = lttng_msgpack_end_map(writer);
42f3ef8c
FD
85end:
86 return ret;
87}
88
89static
90int64_t capture_sequence_element_signed(uint8_t *ptr,
437d5aa5 91 const struct lttng_kernel_type_integer *type)
42f3ef8c
FD
92{
93 int64_t value = 0;
94 unsigned int size = type->size;
11b589f6 95 bool user = type->user;
42f3ef8c
FD
96 bool byte_order_reversed = type->reverse_byte_order;
97
98 switch (size) {
99 case 8:
11b589f6
MD
100 {
101 int8_t tmp;
102
103 if (user) {
104 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int8_t)))
105 tmp = 0;
106 } else {
107 tmp = *ptr;
108 }
109 value = tmp;
42f3ef8c 110 break;
11b589f6 111 }
42f3ef8c
FD
112 case 16:
113 {
114 int16_t tmp;
11b589f6
MD
115
116 if (user) {
117 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int16_t)))
118 tmp = 0;
119 } else {
120 tmp = *(int16_t *) ptr;
121 }
42f3ef8c
FD
122 if (byte_order_reversed)
123 __swab16s(&tmp);
42f3ef8c
FD
124 value = tmp;
125 break;
126 }
127 case 32:
128 {
129 int32_t tmp;
11b589f6
MD
130
131 if (user) {
132 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int32_t)))
133 tmp = 0;
134 } else {
135 tmp = *(int32_t *) ptr;
136 }
42f3ef8c
FD
137 if (byte_order_reversed)
138 __swab32s(&tmp);
42f3ef8c
FD
139 value = tmp;
140 break;
141 }
142 case 64:
143 {
144 int64_t tmp;
11b589f6
MD
145
146 if (user) {
147 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int64_t)))
148 tmp = 0;
149 } else {
150 tmp = *(int64_t *) ptr;
151 }
42f3ef8c
FD
152 if (byte_order_reversed)
153 __swab64s(&tmp);
42f3ef8c
FD
154 value = tmp;
155 break;
156 }
157 default:
736f2dd6 158 WARN_ON_ONCE(1);
42f3ef8c
FD
159 }
160
161 return value;
162}
163
164static
165uint64_t capture_sequence_element_unsigned(uint8_t *ptr,
437d5aa5 166 const struct lttng_kernel_type_integer *type)
42f3ef8c
FD
167{
168 uint64_t value = 0;
169 unsigned int size = type->size;
11b589f6 170 bool user = type->user;
42f3ef8c
FD
171 bool byte_order_reversed = type->reverse_byte_order;
172
173 switch (size) {
174 case 8:
11b589f6
MD
175 {
176 uint8_t tmp;
177
178 if (user) {
179 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint8_t)))
180 tmp = 0;
181 } else {
182 tmp = *ptr;
183 }
184 value = tmp;
42f3ef8c 185 break;
11b589f6 186 }
42f3ef8c
FD
187 case 16:
188 {
189 uint16_t tmp;
11b589f6
MD
190
191 if (user) {
192 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint16_t)))
193 tmp = 0;
194 } else {
195 tmp = *(uint16_t *) ptr;
196 }
42f3ef8c
FD
197 if (byte_order_reversed)
198 __swab16s(&tmp);
42f3ef8c
FD
199 value = tmp;
200 break;
201 }
202 case 32:
203 {
204 uint32_t tmp;
11b589f6
MD
205
206 if (user) {
207 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint32_t)))
208 tmp = 0;
209 } else {
210 tmp = *(uint32_t *) ptr;
211 }
42f3ef8c
FD
212 if (byte_order_reversed)
213 __swab32s(&tmp);
42f3ef8c
FD
214 value = tmp;
215 break;
216 }
217 case 64:
218 {
219 uint64_t tmp;
11b589f6
MD
220
221 if (user) {
222 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint64_t)))
223 tmp = 0;
224 } else {
225 tmp = *(uint64_t *) ptr;
226 }
42f3ef8c
FD
227 if (byte_order_reversed)
228 __swab64s(&tmp);
42f3ef8c
FD
229 value = tmp;
230 break;
231 }
232 default:
736f2dd6 233 WARN_ON_ONCE(1);
42f3ef8c
FD
234 }
235
236 return value;
237}
238
42f3ef8c
FD
239int capture_sequence(struct lttng_msgpack_writer *writer,
240 struct lttng_interpreter_output *output)
241{
437d5aa5
MD
242 const struct lttng_kernel_type_integer *integer_type = NULL;
243 const struct lttng_kernel_type_common *nested_type;
42f3ef8c
FD
244 uint8_t *ptr;
245 bool signedness;
246 int ret, i;
247
248 ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
249 if (ret) {
42f3ef8c
FD
250 goto end;
251 }
252
253 ptr = (uint8_t *) output->u.sequence.ptr;
254 nested_type = output->u.sequence.nested_type;
12bb2edb
MD
255 switch (nested_type->type) {
256 case lttng_kernel_type_integer:
437d5aa5 257 integer_type = lttng_kernel_get_type_integer(nested_type);
42f3ef8c 258 break;
437d5aa5 259 case lttng_kernel_type_enum:
42f3ef8c 260 /* Treat enumeration as an integer. */
437d5aa5 261 integer_type = lttng_kernel_get_type_integer(lttng_kernel_get_type_enum(nested_type)->container_type);
42f3ef8c
FD
262 break;
263 default:
264 /* Capture of array of non-integer are not supported. */
736f2dd6
MD
265 WARN_ON_ONCE(1);
266 ret = -1;
267 goto end;
42f3ef8c
FD
268 }
269 signedness = integer_type->signedness;
270 for (i = 0; i < output->u.sequence.nr_elem; i++) {
271 if (signedness) {
272 ret = lttng_msgpack_write_signed_integer(writer,
273 capture_sequence_element_signed(ptr, integer_type));
274 if (ret) {
42f3ef8c
FD
275 goto end;
276 }
277 } else {
278 ret = lttng_msgpack_write_unsigned_integer(writer,
279 capture_sequence_element_unsigned(ptr, integer_type));
280 if (ret) {
42f3ef8c
FD
281 goto end;
282 }
283 }
284
285 /*
286 * We assume that alignment is smaller or equal to the size.
287 * This currently holds true but if it changes in the future,
288 * we will want to change the pointer arithmetics below to
289 * take into account that the next element might be further
290 * away.
291 */
736f2dd6 292 WARN_ON_ONCE(integer_type->alignment > integer_type->size);
42f3ef8c
FD
293
294 /* Size is in number of bits. */
295 ptr += (integer_type->size / CHAR_BIT) ;
296 }
297
298 ret = lttng_msgpack_end_array(writer);
42f3ef8c
FD
299end:
300 return ret;
301}
302
99d223ad
FD
303static
304int notification_append_capture(
305 struct lttng_event_notifier_notification *notif,
306 struct lttng_interpreter_output *output)
307{
308 struct lttng_msgpack_writer *writer = &notif->writer;
309 int ret = 0;
310
311 switch (output->type) {
312 case LTTNG_INTERPRETER_TYPE_S64:
313 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
99d223ad
FD
314 break;
315 case LTTNG_INTERPRETER_TYPE_U64:
316 ret = lttng_msgpack_write_unsigned_integer(writer, output->u.u);
99d223ad
FD
317 break;
318 case LTTNG_INTERPRETER_TYPE_STRING:
8915cf5e
MD
319 if (output->u.str.user) {
320 ret = lttng_msgpack_write_user_str(writer, output->u.str.user_str);
321 } else {
322 ret = lttng_msgpack_write_str(writer, output->u.str.str);
323 }
99d223ad
FD
324 break;
325 case LTTNG_INTERPRETER_TYPE_SEQUENCE:
326 ret = capture_sequence(writer, output);
99d223ad
FD
327 break;
328 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
329 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
330 ret = capture_enum(writer, output);
99d223ad
FD
331 break;
332 default:
333 ret = -1;
736f2dd6 334 WARN_ON_ONCE(1);
99d223ad 335 }
99d223ad
FD
336 return ret;
337}
338
339static
340int notification_append_empty_capture(
341 struct lttng_event_notifier_notification *notif)
342{
736f2dd6 343 return lttng_msgpack_write_nil(&notif->writer);
99d223ad
FD
344}
345
346static
347int notification_init(struct lttng_event_notifier_notification *notif,
a67ba386 348 struct lttng_kernel_event_notifier *event_notifier)
99d223ad
FD
349{
350 struct lttng_msgpack_writer *writer = &notif->writer;
351 int ret = 0;
352
353 notif->has_captures = false;
354
a67ba386 355 if (event_notifier->priv->num_captures > 0) {
99d223ad
FD
356 lttng_msgpack_writer_init(writer, notif->capture_buf,
357 CAPTURE_BUFFER_SIZE);
358
a67ba386 359 ret = lttng_msgpack_begin_array(writer, event_notifier->priv->num_captures);
99d223ad 360 if (ret) {
99d223ad
FD
361 goto end;
362 }
363
364 notif->has_captures = true;
365 }
366
367end:
368 return ret;
369}
370
99f52fcc 371static
a67ba386 372void record_error(struct lttng_kernel_event_notifier *event_notifier)
99f52fcc
FD
373{
374
a67ba386 375 struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group;
ab04d7b1 376 struct lttng_counter *error_counter;
99f52fcc
FD
377 size_t dimension_index[1];
378 int ret;
379
ab04d7b1 380 /*
6657edec 381 * lttng_smp_load_acquire paired with lttng_smp_store_release orders
ab04d7b1
MD
382 * creation of the error counter and setting error_counter_len
383 * before the error_counter is used.
384 */
6657edec 385 error_counter = lttng_smp_load_acquire(&event_notifier_group->error_counter);
a83d6831 386 /* This group may not have an error counter attached to it. */
ab04d7b1 387 if (!error_counter)
a83d6831
FD
388 return;
389
a67ba386 390 dimension_index[0] = event_notifier->priv->error_counter_index;
99f52fcc 391
ab04d7b1 392 ret = error_counter->ops->counter_add(error_counter->counter,
99f52fcc
FD
393 dimension_index, 1);
394 if (ret)
395 WARN_ON_ONCE(1);
396}
397
99d223ad
FD
398static
399void notification_send(struct lttng_event_notifier_notification *notif,
a67ba386 400 struct lttng_kernel_event_notifier *event_notifier)
21f58fb7 401{
a67ba386 402 struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group;
8a57ec02 403 struct lttng_kernel_ring_buffer_ctx ctx;
606828e4 404 struct lttng_kernel_abi_event_notifier_notification kernel_notif;
99d223ad 405 size_t capture_buffer_content_len, reserve_size;
21f58fb7
FD
406 int ret;
407
99d223ad 408 reserve_size = sizeof(kernel_notif);
a67ba386 409 kernel_notif.token = event_notifier->priv->parent.user_token;
21f58fb7 410
99d223ad
FD
411 if (notif->has_captures) {
412 capture_buffer_content_len = notif->writer.write_pos - notif->writer.buffer;
413 } else {
414 capture_buffer_content_len = 0;
415 }
416
417 WARN_ON_ONCE(capture_buffer_content_len > CAPTURE_BUFFER_SIZE);
418
419 reserve_size += capture_buffer_content_len;
420 kernel_notif.capture_buf_size = capture_buffer_content_len;
421
8a445457 422 lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, reserve_size,
b1199bd3 423 lttng_alignof(kernel_notif), NULL);
c2fb9c1c 424 ret = event_notifier_group->ops->event_reserve(&ctx);
21f58fb7 425 if (ret < 0) {
99f52fcc 426 record_error(event_notifier);
21f58fb7
FD
427 return;
428 }
99d223ad 429
99d223ad
FD
430 /* Write the notif structure. */
431 event_notifier_group->ops->event_write(&ctx, &kernel_notif,
f5ffbd77 432 sizeof(kernel_notif), lttng_alignof(kernel_notif));
99d223ad
FD
433
434 /*
435 * Write the capture buffer. No need to realigned as the below is a raw
436 * char* buffer.
437 */
438 event_notifier_group->ops->event_write(&ctx, &notif->capture_buf,
f5ffbd77 439 capture_buffer_content_len, 1);
99d223ad 440
21f58fb7
FD
441 event_notifier_group->ops->event_commit(&ctx);
442 irq_work_queue(&event_notifier_group->wakeup_pending);
443}
99d223ad 444
a67ba386 445void lttng_event_notifier_notification_send(struct lttng_kernel_event_notifier *event_notifier,
c3eddb2e 446 const char *stack_data,
a92e844e 447 struct lttng_kernel_probe_ctx *probe_ctx,
a67ba386 448 struct lttng_kernel_notification_ctx *notif_ctx)
99d223ad
FD
449{
450 struct lttng_event_notifier_notification notif = { 0 };
99d223ad 451
a67ba386 452 if (unlikely(!READ_ONCE(event_notifier->parent.enabled)))
99d223ad
FD
453 return;
454
736f2dd6
MD
455 if (notification_init(&notif, event_notifier)) {
456 record_error(event_notifier);
99d223ad
FD
457 goto end;
458 }
459
c3eddb2e 460 if (unlikely(notif_ctx->eval_capture)) {
218585b9 461 struct lttng_kernel_bytecode_runtime *capture_bc_runtime;
99d223ad
FD
462
463 /*
464 * Iterate over all the capture bytecodes. If the interpreter
465 * functions returns successfully, append the value of the
466 * `output` parameter to the capture buffer. If the interpreter
467 * fails, append an empty capture to the buffer.
468 */
c3eddb2e 469 list_for_each_entry_rcu(capture_bc_runtime,
a67ba386 470 &event_notifier->priv->capture_bytecode_runtime_head, node) {
99d223ad 471 struct lttng_interpreter_output output;
736f2dd6
MD
472 uint8_t *save_pos;
473 int ret;
99d223ad 474
736f2dd6 475 lttng_msgpack_save_writer_pos(&notif.writer, &save_pos);
8a445457
MD
476 if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
477 stack_data, probe_ctx, &output) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK)
99d223ad
FD
478 ret = notification_append_capture(&notif, &output);
479 else
480 ret = notification_append_empty_capture(&notif);
736f2dd6
MD
481 if (ret) {
482 /*
483 * On append capture error, skip the field
484 * capture by restoring the msgpack writer
485 * position.
486 */
487 lttng_msgpack_restore_writer_pos(&notif.writer, save_pos);
488 }
99d223ad
FD
489 }
490 }
491
492 /*
493 * Send the notification (including the capture buffer) to the
494 * sessiond.
495 */
496 notification_send(&notif, event_notifier);
497end:
498 return;
499}
This page took 0.062078 seconds and 4 git commands to generate.