Tests: Fix: Use '.logfile' instead of '.log' for test app output
[lttng-tools.git] / src / common / config / session-config.cpp
1 /*
2 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include "lttng/tracker.h"
9 #define _LGPL_SOURCE
10 #include "config-internal.hpp"
11 #include "session-config.hpp"
12
13 #include <common/compat/getenv.hpp>
14 #include <common/defaults.hpp>
15 #include <common/dynamic-buffer.hpp>
16 #include <common/error.hpp>
17 #include <common/macros.hpp>
18 #include <common/make-unique-wrapper.hpp>
19 #include <common/utils.hpp>
20
21 #include <lttng/lttng-error.h>
22 #include <lttng/lttng.h>
23 #include <lttng/rotation.h>
24 #include <lttng/snapshot.h>
25 #include <lttng/userspace-probe.h>
26
27 #include <ctype.h>
28 #include <dirent.h>
29 #include <inttypes.h>
30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32 #include <libxml/valid.h>
33 #include <libxml/xmlschemas.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41
42 #define CONFIG_USERSPACE_PROBE_LOOKUP_METHOD_NAME_MAX_LEN 7
43
44 namespace {
45 struct session_config_validation_ctx {
46 xmlSchemaParserCtxtPtr parser_ctx;
47 xmlSchemaPtr schema;
48 xmlSchemaValidCtxtPtr schema_validation_ctx;
49 };
50 } /* namespace */
51
52 const char *const config_element_all = "all";
53 LTTNG_EXPORT const char *config_xml_encoding = "UTF-8";
54 LTTNG_EXPORT size_t config_xml_encoding_bytes_per_char = 2; /* Size of the encoding's largest
55 character */
56 LTTNG_EXPORT const char *config_xml_indent_string = "\t";
57 LTTNG_EXPORT const char *config_xml_true = "true";
58 LTTNG_EXPORT const char *config_xml_false = "false";
59
60 const char *const config_element_channel = "channel";
61 const char *const config_element_channels = "channels";
62 const char *const config_element_domain = "domain";
63 const char *const config_element_domains = "domains";
64 const char *const config_element_event = "event";
65 const char *const config_element_events = "events";
66 const char *const config_element_context = "context";
67 const char *const config_element_contexts = "contexts";
68 const char *const config_element_attributes = "attributes";
69 const char *const config_element_exclusion = "exclusion";
70 const char *const config_element_exclusions = "exclusions";
71 const char *const config_element_function_attributes = "function_attributes";
72 const char *const config_element_probe_attributes = "probe_attributes";
73 const char *const config_element_symbol_name = "symbol_name";
74 const char *const config_element_address = "address";
75 const char *const config_element_offset = "offset";
76
77 const char *const config_element_userspace_probe_lookup = "lookup_method";
78 const char *const config_element_userspace_probe_lookup_function_default = "DEFAULT";
79 const char *const config_element_userspace_probe_lookup_function_elf = "ELF";
80 const char *const config_element_userspace_probe_lookup_tracepoint_sdt = "SDT";
81 const char *const config_element_userspace_probe_location_binary_path = "binary_path";
82 const char *const config_element_userspace_probe_function_attributes =
83 "userspace_probe_function_attributes";
84 const char *const config_element_userspace_probe_function_location_function_name = "function_name";
85 const char *const config_element_userspace_probe_tracepoint_attributes =
86 "userspace_probe_tracepoint_attributes";
87 const char *const config_element_userspace_probe_tracepoint_location_provider_name =
88 "provider_name";
89 const char *const config_element_userspace_probe_tracepoint_location_probe_name = "probe_name";
90
91 const char *const config_element_name = "name";
92 const char *const config_element_enabled = "enabled";
93 const char *const config_element_overwrite_mode = "overwrite_mode";
94 const char *const config_element_subbuf_size = "subbuffer_size";
95 const char *const config_element_num_subbuf = "subbuffer_count";
96 const char *const config_element_switch_timer_interval = "switch_timer_interval";
97 const char *const config_element_read_timer_interval = "read_timer_interval";
98 const char *const config_element_monitor_timer_interval = "monitor_timer_interval";
99 const char *const config_element_blocking_timeout = "blocking_timeout";
100 const char *const config_element_output = "output";
101 const char *const config_element_output_type = "output_type";
102 const char *const config_element_tracefile_size = "tracefile_size";
103 const char *const config_element_tracefile_count = "tracefile_count";
104 const char *const config_element_live_timer_interval = "live_timer_interval";
105 const char *const config_element_discarded_events = "discarded_events";
106 const char *const config_element_lost_packets = "lost_packets";
107 const char *const config_element_type = "type";
108 const char *const config_element_buffer_type = "buffer_type";
109 const char *const config_element_session = "session";
110 const char *const config_element_sessions = "sessions";
111 const char *const config_element_context_perf = "perf";
112 const char *const config_element_context_app = "app";
113 const char *const config_element_context_app_provider_name = "provider_name";
114 const char *const config_element_context_app_ctx_name = "ctx_name";
115 const char *const config_element_config = "config";
116 const char *const config_element_started = "started";
117 const char *const config_element_snapshot_mode = "snapshot_mode";
118 const char *const config_element_loglevel = "loglevel";
119 const char *const config_element_loglevel_type = "loglevel_type";
120 const char *const config_element_filter = "filter";
121 const char *const config_element_filter_expression = "filter_expression";
122 const char *const config_element_snapshot_outputs = "snapshot_outputs";
123 const char *const config_element_consumer_output = "consumer_output";
124 const char *const config_element_destination = "destination";
125 const char *const config_element_path = "path";
126 const char *const config_element_net_output = "net_output";
127 const char *const config_element_control_uri = "control_uri";
128 const char *const config_element_data_uri = "data_uri";
129 const char *const config_element_max_size = "max_size";
130 const char *const config_element_pid = "pid";
131 const char *const config_element_pids = "pids";
132 const char *const config_element_shared_memory_path = "shared_memory_path";
133
134 const char *const config_element_process_attr_id = "id";
135 const char *const config_element_process_attr_tracker_pid = "pid_process_attr_tracker";
136 const char *const config_element_process_attr_tracker_vpid = "vpid_process_attr_tracker";
137 const char *const config_element_process_attr_tracker_uid = "uid_process_attr_tracker";
138 const char *const config_element_process_attr_tracker_vuid = "vuid_process_attr_tracker";
139 const char *const config_element_process_attr_tracker_gid = "gid_process_attr_tracker";
140 const char *const config_element_process_attr_tracker_vgid = "vgid_process_attr_tracker";
141 const char *const config_element_process_attr_trackers = "process_attr_trackers";
142 const char *const config_element_process_attr_values = "process_attr_values";
143 const char *const config_element_process_attr_value_type = "process_attr_value_type";
144 const char *const config_element_process_attr_pid_value = "pid";
145 const char *const config_element_process_attr_vpid_value = "vpid";
146 const char *const config_element_process_attr_uid_value = "uid";
147 const char *const config_element_process_attr_vuid_value = "vuid";
148 const char *const config_element_process_attr_gid_value = "gid";
149 const char *const config_element_process_attr_vgid_value = "vgid";
150 const char *const config_element_process_attr_tracker_type = "process_attr_tracker_type";
151
152 /* Used for support of legacy tracker serialization (< 2.12). */
153 const char *const config_element_trackers_legacy = "trackers";
154 const char *const config_element_pid_tracker_legacy = "pid_tracker";
155 const char *const config_element_tracker_targets_legacy = "targets";
156 const char *const config_element_tracker_pid_legacy = "pid";
157
158 const char *const config_element_rotation_schedules = "rotation_schedules";
159 const char *const config_element_rotation_schedule_periodic = "periodic";
160 const char *const config_element_rotation_schedule_periodic_time_us = "time_us";
161 const char *const config_element_rotation_schedule_size_threshold = "size_threshold";
162 const char *const config_element_rotation_schedule_size_threshold_bytes = "bytes";
163
164 const char *const config_domain_type_kernel = "KERNEL";
165 const char *const config_domain_type_ust = "UST";
166 const char *const config_domain_type_jul = "JUL";
167 const char *const config_domain_type_log4j = "LOG4J";
168 const char *const config_domain_type_log4j2 = "LOG4J2";
169 const char *const config_domain_type_python = "PYTHON";
170
171 const char *const config_buffer_type_per_pid = "PER_PID";
172 const char *const config_buffer_type_per_uid = "PER_UID";
173 const char *const config_buffer_type_global = "GLOBAL";
174
175 const char *const config_overwrite_mode_discard = "DISCARD";
176 const char *const config_overwrite_mode_overwrite = "OVERWRITE";
177
178 const char *const config_output_type_splice = "SPLICE";
179 const char *const config_output_type_mmap = "MMAP";
180
181 const char *const config_loglevel_type_all = "ALL";
182 const char *const config_loglevel_type_range = "RANGE";
183 const char *const config_loglevel_type_single = "SINGLE";
184
185 const char *const config_event_type_all = "ALL";
186 const char *const config_event_type_tracepoint = "TRACEPOINT";
187 const char *const config_event_type_probe = "PROBE";
188 const char *const config_event_type_userspace_probe = "USERSPACE_PROBE";
189 const char *const config_event_type_function = "FUNCTION";
190 const char *const config_event_type_function_entry = "FUNCTION_ENTRY";
191 const char *const config_event_type_noop = "NOOP";
192 const char *const config_event_type_syscall = "SYSCALL";
193 const char *const config_event_type_kprobe = "KPROBE";
194 const char *const config_event_type_kretprobe = "KRETPROBE";
195
196 const char *const config_event_context_pid = "PID";
197 const char *const config_event_context_procname = "PROCNAME";
198 const char *const config_event_context_prio = "PRIO";
199 const char *const config_event_context_nice = "NICE";
200 const char *const config_event_context_vpid = "VPID";
201 const char *const config_event_context_tid = "TID";
202 const char *const config_event_context_vtid = "VTID";
203 const char *const config_event_context_ppid = "PPID";
204 const char *const config_event_context_vppid = "VPPID";
205 const char *const config_event_context_pthread_id = "PTHREAD_ID";
206 const char *const config_event_context_hostname = "HOSTNAME";
207 const char *const config_event_context_ip = "IP";
208 const char *const config_event_context_perf_thread_counter = "PERF_THREAD_COUNTER";
209 const char *const config_event_context_app = "APP";
210 const char *const config_event_context_interruptible = "INTERRUPTIBLE";
211 const char *const config_event_context_preemptible = "PREEMPTIBLE";
212 const char *const config_event_context_need_reschedule = "NEED_RESCHEDULE";
213 const char *const config_event_context_migratable = "MIGRATABLE";
214 const char *const config_event_context_callstack_user = "CALLSTACK_USER";
215 const char *const config_event_context_callstack_kernel = "CALLSTACK_KERNEL";
216 const char *const config_event_context_cgroup_ns = "CGROUP_NS";
217 const char *const config_event_context_ipc_ns = "IPC_NS";
218 const char *const config_event_context_mnt_ns = "MNT_NS";
219 const char *const config_event_context_net_ns = "NET_NS";
220 const char *const config_event_context_pid_ns = "PID_NS";
221 const char *const config_event_context_time_ns = "TIME_NS";
222 const char *const config_event_context_user_ns = "USER_NS";
223 const char *const config_event_context_uts_ns = "UTS_NS";
224 const char *const config_event_context_uid = "UID";
225 const char *const config_event_context_euid = "EUID";
226 const char *const config_event_context_suid = "SUID";
227 const char *const config_event_context_gid = "GID";
228 const char *const config_event_context_egid = "EGID";
229 const char *const config_event_context_sgid = "SGID";
230 const char *const config_event_context_vuid = "VUID";
231 const char *const config_event_context_veuid = "VEUID";
232 const char *const config_event_context_vsuid = "VSUID";
233 const char *const config_event_context_vgid = "VGID";
234 const char *const config_event_context_vegid = "VEGID";
235 const char *const config_event_context_vsgid = "VSGID";
236
237 /* Deprecated symbols */
238 LTTNG_EXPORT const char *config_element_perf;
239
240 enum process_event_node_phase {
241 CREATION = 0,
242 ENABLE = 1,
243 };
244
245 namespace {
246 struct consumer_output {
247 int enabled;
248 char *path;
249 char *control_uri;
250 char *data_uri;
251 };
252 } /* namespace */
253
254 /*
255 * Returns a xmlChar string which must be released using xmlFree().
256 */
257 static xmlChar *encode_string(const char *in_str)
258 {
259 xmlChar *out_str = nullptr;
260 xmlCharEncodingHandlerPtr handler;
261 int out_len, ret, in_len;
262
263 LTTNG_ASSERT(in_str);
264
265 handler = xmlFindCharEncodingHandler(config_xml_encoding);
266 if (!handler) {
267 ERR("xmlFindCharEncodingHandler return NULL!. Configure issue!");
268 goto end;
269 }
270
271 in_len = strlen(in_str);
272 /*
273 * Add 1 byte for the NULL terminted character. The factor 4 here is
274 * used because UTF-8 characters can take up to 4 bytes.
275 */
276 out_len = (in_len * 4) + 1;
277 out_str = (xmlChar *) xmlMalloc(out_len);
278 if (!out_str) {
279 goto end;
280 }
281
282 ret = handler->input(out_str, &out_len, (const xmlChar *) in_str, &in_len);
283 if (ret < 0) {
284 xmlFree(out_str);
285 out_str = nullptr;
286 goto end;
287 }
288
289 /* out_len is now the size of out_str */
290 out_str[out_len] = '\0';
291 end:
292 return out_str;
293 }
294
295 struct config_writer *config_writer_create(int fd_output, int indent)
296 {
297 int ret;
298 struct config_writer *writer;
299 xmlOutputBufferPtr buffer;
300
301 writer = zmalloc<config_writer>();
302 if (!writer) {
303 PERROR("zmalloc config_writer_create");
304 goto end;
305 }
306
307 buffer = xmlOutputBufferCreateFd(fd_output, nullptr);
308 if (!buffer) {
309 goto error_destroy;
310 }
311
312 writer->writer = xmlNewTextWriter(buffer);
313 ret = xmlTextWriterStartDocument(writer->writer, nullptr, config_xml_encoding, nullptr);
314 if (ret < 0) {
315 goto error_destroy;
316 }
317
318 ret = xmlTextWriterSetIndentString(writer->writer, BAD_CAST config_xml_indent_string);
319 if (ret) {
320 goto error_destroy;
321 }
322
323 ret = xmlTextWriterSetIndent(writer->writer, indent);
324 if (ret) {
325 goto error_destroy;
326 }
327
328 end:
329 return writer;
330 error_destroy:
331 config_writer_destroy(writer);
332 return nullptr;
333 }
334
335 int config_writer_destroy(struct config_writer *writer)
336 {
337 int ret = 0;
338
339 if (!writer) {
340 ret = -EINVAL;
341 goto end;
342 }
343
344 if (xmlTextWriterEndDocument(writer->writer) < 0) {
345 WARN("Could not close XML document");
346 ret = -EIO;
347 }
348
349 if (writer->writer) {
350 xmlFreeTextWriter(writer->writer);
351 }
352
353 free(writer);
354 end:
355 return ret;
356 }
357
358 int config_writer_open_element(struct config_writer *writer, const char *element_name)
359 {
360 int ret;
361 xmlChar *encoded_element_name;
362
363 if (!writer || !writer->writer || !element_name || !element_name[0]) {
364 ret = -1;
365 goto end;
366 }
367
368 encoded_element_name = encode_string(element_name);
369 if (!encoded_element_name) {
370 ret = -1;
371 goto end;
372 }
373
374 ret = xmlTextWriterStartElement(writer->writer, encoded_element_name);
375 xmlFree(encoded_element_name);
376 end:
377 return ret >= 0 ? 0 : ret;
378 }
379
380 int config_writer_write_attribute(struct config_writer *writer, const char *name, const char *value)
381 {
382 int ret;
383 xmlChar *encoded_name = nullptr;
384 xmlChar *encoded_value = nullptr;
385
386 if (!writer || !writer->writer || !name || !name[0]) {
387 ret = -1;
388 goto end;
389 }
390
391 encoded_name = encode_string(name);
392 if (!encoded_name) {
393 ret = -1;
394 goto end;
395 }
396
397 encoded_value = encode_string(value);
398 if (!encoded_value) {
399 ret = -1;
400 goto end;
401 }
402
403 ret = xmlTextWriterWriteAttribute(writer->writer, encoded_name, encoded_value);
404 end:
405 xmlFree(encoded_name);
406 xmlFree(encoded_value);
407 return ret >= 0 ? 0 : ret;
408 }
409
410 int config_writer_close_element(struct config_writer *writer)
411 {
412 int ret;
413
414 if (!writer || !writer->writer) {
415 ret = -1;
416 goto end;
417 }
418
419 ret = xmlTextWriterEndElement(writer->writer);
420 end:
421 return ret >= 0 ? 0 : ret;
422 }
423
424 int config_writer_write_element_unsigned_int(struct config_writer *writer,
425 const char *element_name,
426 uint64_t value)
427 {
428 int ret;
429 xmlChar *encoded_element_name;
430
431 if (!writer || !writer->writer || !element_name || !element_name[0]) {
432 ret = -1;
433 goto end;
434 }
435
436 encoded_element_name = encode_string(element_name);
437 if (!encoded_element_name) {
438 ret = -1;
439 goto end;
440 }
441
442 ret = xmlTextWriterWriteFormatElement(
443 writer->writer, encoded_element_name, "%" PRIu64, value);
444 xmlFree(encoded_element_name);
445 end:
446 return ret >= 0 ? 0 : ret;
447 }
448
449 int config_writer_write_element_signed_int(struct config_writer *writer,
450 const char *element_name,
451 int64_t value)
452 {
453 int ret;
454 xmlChar *encoded_element_name;
455
456 if (!writer || !writer->writer || !element_name || !element_name[0]) {
457 ret = -1;
458 goto end;
459 }
460
461 encoded_element_name = encode_string(element_name);
462 if (!encoded_element_name) {
463 ret = -1;
464 goto end;
465 }
466
467 ret = xmlTextWriterWriteFormatElement(
468 writer->writer, encoded_element_name, "%" PRIi64, value);
469 xmlFree(encoded_element_name);
470 end:
471 return ret >= 0 ? 0 : ret;
472 }
473
474 int config_writer_write_element_bool(struct config_writer *writer,
475 const char *element_name,
476 int value)
477 {
478 return config_writer_write_element_string(
479 writer, element_name, value ? config_xml_true : config_xml_false);
480 }
481
482 int config_writer_write_element_double(struct config_writer *writer,
483 const char *element_name,
484 double value)
485 {
486 int ret;
487 xmlChar *encoded_element_name;
488
489 if (!writer || !writer->writer || !element_name || !element_name[0]) {
490 ret = -1;
491 goto end;
492 }
493
494 encoded_element_name = encode_string(element_name);
495 if (!encoded_element_name) {
496 ret = -1;
497 goto end;
498 }
499
500 ret = xmlTextWriterWriteFormatElement(writer->writer, encoded_element_name, "%f", value);
501 xmlFree(encoded_element_name);
502 end:
503 return ret >= 0 ? 0 : ret;
504 }
505
506 int config_writer_write_element_string(struct config_writer *writer,
507 const char *element_name,
508 const char *value)
509 {
510 int ret;
511 xmlChar *encoded_element_name = nullptr;
512 xmlChar *encoded_value = nullptr;
513
514 if (!writer || !writer->writer || !element_name || !element_name[0] || !value) {
515 ret = -1;
516 goto end;
517 }
518
519 encoded_element_name = encode_string(element_name);
520 if (!encoded_element_name) {
521 ret = -1;
522 goto end;
523 }
524
525 encoded_value = encode_string(value);
526 if (!encoded_value) {
527 ret = -1;
528 goto end;
529 }
530
531 ret = xmlTextWriterWriteElement(writer->writer, encoded_element_name, encoded_value);
532 end:
533 xmlFree(encoded_element_name);
534 xmlFree(encoded_value);
535 return ret >= 0 ? 0 : ret;
536 }
537
538 static ATTR_FORMAT_PRINTF(2, 3) void xml_error_handler(void *ctx __attribute__((unused)),
539 const char *format,
540 ...)
541 {
542 char *errMsg;
543 va_list args;
544 int ret;
545
546 va_start(args, format);
547 ret = vasprintf(&errMsg, format, args);
548 va_end(args);
549 if (ret == -1) {
550 ERR("String allocation failed in xml error handler");
551 return;
552 }
553
554 fprintf(stderr, "XML Error: %s", errMsg);
555 free(errMsg);
556 }
557
558 static void fini_session_config_validation_ctx(struct session_config_validation_ctx *ctx)
559 {
560 if (ctx->parser_ctx) {
561 xmlSchemaFreeParserCtxt(ctx->parser_ctx);
562 }
563
564 if (ctx->schema) {
565 xmlSchemaFree(ctx->schema);
566 }
567
568 if (ctx->schema_validation_ctx) {
569 xmlSchemaFreeValidCtxt(ctx->schema_validation_ctx);
570 }
571
572 memset(ctx, 0, sizeof(struct session_config_validation_ctx));
573 }
574
575 static char *get_session_config_xsd_path()
576 {
577 char *xsd_path;
578 const char *base_path = lttng_secure_getenv(DEFAULT_SESSION_CONFIG_XSD_PATH_ENV);
579 size_t base_path_len;
580 size_t max_path_len;
581
582 if (!base_path) {
583 base_path = DEFAULT_SESSION_CONFIG_XSD_PATH;
584 }
585
586 base_path_len = strlen(base_path);
587 max_path_len = base_path_len + sizeof(DEFAULT_SESSION_CONFIG_XSD_FILENAME) + 1;
588 xsd_path = zmalloc<char>(max_path_len);
589 if (!xsd_path) {
590 goto end;
591 }
592
593 strcpy(xsd_path, base_path);
594 if (xsd_path[base_path_len - 1] != '/') {
595 xsd_path[base_path_len++] = '/';
596 }
597
598 strcpy(xsd_path + base_path_len, DEFAULT_SESSION_CONFIG_XSD_FILENAME);
599 end:
600 return xsd_path;
601 }
602
603 static int init_session_config_validation_ctx(struct session_config_validation_ctx *ctx)
604 {
605 int ret;
606 char *xsd_path = get_session_config_xsd_path();
607
608 if (!xsd_path) {
609 ret = -LTTNG_ERR_NOMEM;
610 goto end;
611 }
612
613 ctx->parser_ctx = xmlSchemaNewParserCtxt(xsd_path);
614 if (!ctx->parser_ctx) {
615 ERR("XSD parser context creation failed");
616 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
617 goto end;
618 }
619 xmlSchemaSetParserErrors(ctx->parser_ctx, xml_error_handler, xml_error_handler, nullptr);
620
621 ctx->schema = xmlSchemaParse(ctx->parser_ctx);
622 if (!ctx->schema) {
623 ERR("XSD parsing failed");
624 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
625 goto end;
626 }
627
628 ctx->schema_validation_ctx = xmlSchemaNewValidCtxt(ctx->schema);
629 if (!ctx->schema_validation_ctx) {
630 ERR("XSD validation context creation failed");
631 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
632 goto end;
633 }
634
635 xmlSchemaSetValidErrors(
636 ctx->schema_validation_ctx, xml_error_handler, xml_error_handler, nullptr);
637 ret = 0;
638
639 end:
640 if (ret) {
641 fini_session_config_validation_ctx(ctx);
642 }
643
644 free(xsd_path);
645 return ret;
646 }
647
648 static int parse_uint(xmlChar *str, uint64_t *val)
649 {
650 int ret;
651 char *endptr;
652
653 if (!str || !val) {
654 ret = -1;
655 goto end;
656 }
657
658 *val = strtoull((const char *) str, &endptr, 10);
659 if (!endptr || *endptr) {
660 ret = -1;
661 } else {
662 ret = 0;
663 }
664
665 end:
666 return ret;
667 }
668
669 static int parse_int(xmlChar *str, int64_t *val)
670 {
671 int ret;
672 char *endptr;
673
674 if (!str || !val) {
675 ret = -1;
676 goto end;
677 }
678
679 *val = strtoll((const char *) str, &endptr, 10);
680 if (!endptr || *endptr) {
681 ret = -1;
682 } else {
683 ret = 0;
684 }
685
686 end:
687 return ret;
688 }
689
690 static int parse_bool(xmlChar *str, int *val)
691 {
692 int ret = 0;
693
694 if (!str || !val) {
695 ret = -1;
696 goto end;
697 }
698
699 if (!strcmp((const char *) str, config_xml_true) || !strcmp((const char *) str, "1")) {
700 *val = 1;
701 } else if (!strcmp((const char *) str, config_xml_false) ||
702 !strcmp((const char *) str, "0")) {
703 *val = 0;
704 } else {
705 WARN("Invalid boolean value encountered (%s).", (const char *) str);
706 ret = -1;
707 }
708 end:
709 return ret;
710 }
711
712 static int get_domain_type(xmlChar *domain)
713 {
714 int ret;
715
716 if (!domain) {
717 goto error;
718 }
719
720 if (!strcmp((char *) domain, config_domain_type_kernel)) {
721 ret = LTTNG_DOMAIN_KERNEL;
722 } else if (!strcmp((char *) domain, config_domain_type_ust)) {
723 ret = LTTNG_DOMAIN_UST;
724 } else if (!strcmp((char *) domain, config_domain_type_jul)) {
725 ret = LTTNG_DOMAIN_JUL;
726 } else if (!strcmp((char *) domain, config_domain_type_log4j)) {
727 ret = LTTNG_DOMAIN_LOG4J;
728 } else if (!strcmp((char *) domain, config_domain_type_log4j2)) {
729 ret = LTTNG_DOMAIN_LOG4J2;
730 } else if (!strcmp((char *) domain, config_domain_type_python)) {
731 ret = LTTNG_DOMAIN_PYTHON;
732 } else {
733 goto error;
734 }
735
736 return ret;
737 error:
738 return -1;
739 }
740
741 static int get_buffer_type(xmlChar *buffer_type)
742 {
743 int ret;
744
745 if (!buffer_type) {
746 goto error;
747 }
748
749 if (!strcmp((char *) buffer_type, config_buffer_type_global)) {
750 ret = LTTNG_BUFFER_GLOBAL;
751 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_uid)) {
752 ret = LTTNG_BUFFER_PER_UID;
753 } else if (!strcmp((char *) buffer_type, config_buffer_type_per_pid)) {
754 ret = LTTNG_BUFFER_PER_PID;
755 } else {
756 goto error;
757 }
758
759 return ret;
760 error:
761 return -1;
762 }
763
764 static int get_overwrite_mode(xmlChar *overwrite_mode)
765 {
766 int ret;
767
768 if (!overwrite_mode) {
769 goto error;
770 }
771
772 if (!strcmp((char *) overwrite_mode, config_overwrite_mode_overwrite)) {
773 ret = 1;
774 } else if (!strcmp((char *) overwrite_mode, config_overwrite_mode_discard)) {
775 ret = 0;
776 } else {
777 goto error;
778 }
779
780 return ret;
781 error:
782 return -1;
783 }
784
785 static int get_output_type(xmlChar *output_type)
786 {
787 int ret;
788
789 if (!output_type) {
790 goto error;
791 }
792
793 if (!strcmp((char *) output_type, config_output_type_mmap)) {
794 ret = LTTNG_EVENT_MMAP;
795 } else if (!strcmp((char *) output_type, config_output_type_splice)) {
796 ret = LTTNG_EVENT_SPLICE;
797 } else {
798 goto error;
799 }
800
801 return ret;
802 error:
803 return -1;
804 }
805
806 static int get_event_type(xmlChar *event_type)
807 {
808 int ret;
809
810 if (!event_type) {
811 goto error;
812 }
813
814 if (!strcmp((char *) event_type, config_event_type_all)) {
815 ret = LTTNG_EVENT_ALL;
816 } else if (!strcmp((char *) event_type, config_event_type_tracepoint)) {
817 ret = LTTNG_EVENT_TRACEPOINT;
818 } else if (!strcmp((char *) event_type, config_event_type_probe)) {
819 ret = LTTNG_EVENT_PROBE;
820 } else if (!strcmp((char *) event_type, config_event_type_userspace_probe)) {
821 ret = LTTNG_EVENT_USERSPACE_PROBE;
822 } else if (!strcmp((char *) event_type, config_event_type_function)) {
823 ret = LTTNG_EVENT_FUNCTION;
824 } else if (!strcmp((char *) event_type, config_event_type_function_entry)) {
825 ret = LTTNG_EVENT_FUNCTION_ENTRY;
826 } else if (!strcmp((char *) event_type, config_event_type_noop)) {
827 ret = LTTNG_EVENT_NOOP;
828 } else if (!strcmp((char *) event_type, config_event_type_syscall)) {
829 ret = LTTNG_EVENT_SYSCALL;
830 } else {
831 goto error;
832 }
833
834 return ret;
835 error:
836 return -1;
837 }
838
839 static int get_loglevel_type(xmlChar *loglevel_type)
840 {
841 int ret;
842
843 if (!loglevel_type) {
844 goto error;
845 }
846
847 if (!strcmp((char *) loglevel_type, config_loglevel_type_all)) {
848 ret = LTTNG_EVENT_LOGLEVEL_ALL;
849 } else if (!strcmp((char *) loglevel_type, config_loglevel_type_range)) {
850 ret = LTTNG_EVENT_LOGLEVEL_RANGE;
851 } else if (!strcmp((char *) loglevel_type, config_loglevel_type_single)) {
852 ret = LTTNG_EVENT_LOGLEVEL_SINGLE;
853 } else {
854 goto error;
855 }
856
857 return ret;
858 error:
859 return -1;
860 }
861
862 /*
863 * Return the context type or -1 on error.
864 */
865 static int get_context_type(xmlChar *context_type)
866 {
867 int ret;
868
869 if (!context_type) {
870 goto error;
871 }
872
873 if (!strcmp((char *) context_type, config_event_context_pid)) {
874 ret = LTTNG_EVENT_CONTEXT_PID;
875 } else if (!strcmp((char *) context_type, config_event_context_procname)) {
876 ret = LTTNG_EVENT_CONTEXT_PROCNAME;
877 } else if (!strcmp((char *) context_type, config_event_context_prio)) {
878 ret = LTTNG_EVENT_CONTEXT_PRIO;
879 } else if (!strcmp((char *) context_type, config_event_context_nice)) {
880 ret = LTTNG_EVENT_CONTEXT_NICE;
881 } else if (!strcmp((char *) context_type, config_event_context_vpid)) {
882 ret = LTTNG_EVENT_CONTEXT_VPID;
883 } else if (!strcmp((char *) context_type, config_event_context_tid)) {
884 ret = LTTNG_EVENT_CONTEXT_TID;
885 } else if (!strcmp((char *) context_type, config_event_context_vtid)) {
886 ret = LTTNG_EVENT_CONTEXT_VTID;
887 } else if (!strcmp((char *) context_type, config_event_context_ppid)) {
888 ret = LTTNG_EVENT_CONTEXT_PPID;
889 } else if (!strcmp((char *) context_type, config_event_context_vppid)) {
890 ret = LTTNG_EVENT_CONTEXT_VPPID;
891 } else if (!strcmp((char *) context_type, config_event_context_pthread_id)) {
892 ret = LTTNG_EVENT_CONTEXT_PTHREAD_ID;
893 } else if (!strcmp((char *) context_type, config_event_context_hostname)) {
894 ret = LTTNG_EVENT_CONTEXT_HOSTNAME;
895 } else if (!strcmp((char *) context_type, config_event_context_ip)) {
896 ret = LTTNG_EVENT_CONTEXT_IP;
897 } else if (!strcmp((char *) context_type, config_event_context_interruptible)) {
898 ret = LTTNG_EVENT_CONTEXT_INTERRUPTIBLE;
899 } else if (!strcmp((char *) context_type, config_event_context_preemptible)) {
900 ret = LTTNG_EVENT_CONTEXT_PREEMPTIBLE;
901 } else if (!strcmp((char *) context_type, config_event_context_need_reschedule)) {
902 ret = LTTNG_EVENT_CONTEXT_NEED_RESCHEDULE;
903 } else if (!strcmp((char *) context_type, config_event_context_migratable)) {
904 ret = LTTNG_EVENT_CONTEXT_MIGRATABLE;
905 } else if (!strcmp((char *) context_type, config_event_context_callstack_user)) {
906 ret = LTTNG_EVENT_CONTEXT_CALLSTACK_USER;
907 } else if (!strcmp((char *) context_type, config_event_context_callstack_kernel)) {
908 ret = LTTNG_EVENT_CONTEXT_CALLSTACK_KERNEL;
909 } else if (!strcmp((char *) context_type, config_event_context_cgroup_ns)) {
910 ret = LTTNG_EVENT_CONTEXT_CGROUP_NS;
911 } else if (!strcmp((char *) context_type, config_event_context_ipc_ns)) {
912 ret = LTTNG_EVENT_CONTEXT_IPC_NS;
913 } else if (!strcmp((char *) context_type, config_event_context_mnt_ns)) {
914 ret = LTTNG_EVENT_CONTEXT_MNT_NS;
915 } else if (!strcmp((char *) context_type, config_event_context_net_ns)) {
916 ret = LTTNG_EVENT_CONTEXT_NET_NS;
917 } else if (!strcmp((char *) context_type, config_event_context_pid_ns)) {
918 ret = LTTNG_EVENT_CONTEXT_PID_NS;
919 } else if (!strcmp((char *) context_type, config_event_context_time_ns)) {
920 ret = LTTNG_EVENT_CONTEXT_TIME_NS;
921 } else if (!strcmp((char *) context_type, config_event_context_user_ns)) {
922 ret = LTTNG_EVENT_CONTEXT_USER_NS;
923 } else if (!strcmp((char *) context_type, config_event_context_uts_ns)) {
924 ret = LTTNG_EVENT_CONTEXT_UTS_NS;
925 } else if (!strcmp((char *) context_type, config_event_context_uid)) {
926 ret = LTTNG_EVENT_CONTEXT_UID;
927 } else if (!strcmp((char *) context_type, config_event_context_euid)) {
928 ret = LTTNG_EVENT_CONTEXT_EUID;
929 } else if (!strcmp((char *) context_type, config_event_context_suid)) {
930 ret = LTTNG_EVENT_CONTEXT_SUID;
931 } else if (!strcmp((char *) context_type, config_event_context_gid)) {
932 ret = LTTNG_EVENT_CONTEXT_GID;
933 } else if (!strcmp((char *) context_type, config_event_context_egid)) {
934 ret = LTTNG_EVENT_CONTEXT_EGID;
935 } else if (!strcmp((char *) context_type, config_event_context_sgid)) {
936 ret = LTTNG_EVENT_CONTEXT_SGID;
937 } else if (!strcmp((char *) context_type, config_event_context_vuid)) {
938 ret = LTTNG_EVENT_CONTEXT_VUID;
939 } else if (!strcmp((char *) context_type, config_event_context_veuid)) {
940 ret = LTTNG_EVENT_CONTEXT_VEUID;
941 } else if (!strcmp((char *) context_type, config_event_context_vsuid)) {
942 ret = LTTNG_EVENT_CONTEXT_VSUID;
943 } else if (!strcmp((char *) context_type, config_event_context_vgid)) {
944 ret = LTTNG_EVENT_CONTEXT_VGID;
945 } else if (!strcmp((char *) context_type, config_event_context_vegid)) {
946 ret = LTTNG_EVENT_CONTEXT_VEGID;
947 } else if (!strcmp((char *) context_type, config_event_context_vsgid)) {
948 ret = LTTNG_EVENT_CONTEXT_VSGID;
949 } else {
950 goto error;
951 }
952
953 return ret;
954 error:
955 return -1;
956 }
957
958 static int init_domain(xmlNodePtr domain_node, struct lttng_domain *domain)
959 {
960 int ret;
961 xmlNodePtr node;
962
963 for (node = xmlFirstElementChild(domain_node); node; node = xmlNextElementSibling(node)) {
964 if (!strcmp((const char *) node->name, config_element_type)) {
965 /* domain type */
966 xmlChar *node_content = xmlNodeGetContent(node);
967 if (!node_content) {
968 ret = -LTTNG_ERR_NOMEM;
969 goto end;
970 }
971
972 ret = get_domain_type(node_content);
973 free(node_content);
974 if (ret < 0) {
975 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
976 goto end;
977 }
978
979 domain->type = (lttng_domain_type) ret;
980 } else if (!strcmp((const char *) node->name, config_element_buffer_type)) {
981 /* buffer type */
982 xmlChar *node_content = xmlNodeGetContent(node);
983 if (!node_content) {
984 ret = -LTTNG_ERR_NOMEM;
985 goto end;
986 }
987
988 ret = get_buffer_type(node_content);
989 free(node_content);
990 if (ret < 0) {
991 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
992 goto end;
993 }
994
995 domain->buf_type = (lttng_buffer_type) ret;
996 }
997 }
998 ret = 0;
999 end:
1000 return ret;
1001 }
1002
1003 static int get_net_output_uris(xmlNodePtr net_output_node, char **control_uri, char **data_uri)
1004 {
1005 xmlNodePtr node;
1006
1007 for (node = xmlFirstElementChild(net_output_node); node;
1008 node = xmlNextElementSibling(node)) {
1009 if (!strcmp((const char *) node->name, config_element_control_uri)) {
1010 /* control_uri */
1011 *control_uri = (char *) xmlNodeGetContent(node);
1012 if (!*control_uri) {
1013 break;
1014 }
1015 } else {
1016 /* data_uri */
1017 *data_uri = (char *) xmlNodeGetContent(node);
1018 if (!*data_uri) {
1019 break;
1020 }
1021 }
1022 }
1023
1024 return *control_uri || *data_uri ? 0 : -LTTNG_ERR_LOAD_INVALID_CONFIG;
1025 }
1026
1027 static int process_consumer_output(xmlNodePtr consumer_output_node, struct consumer_output *output)
1028 {
1029 int ret;
1030 xmlNodePtr node;
1031
1032 LTTNG_ASSERT(output);
1033
1034 for (node = xmlFirstElementChild(consumer_output_node); node;
1035 node = xmlNextElementSibling(node)) {
1036 if (!strcmp((const char *) node->name, config_element_enabled)) {
1037 xmlChar *enabled_str = xmlNodeGetContent(node);
1038
1039 /* enabled */
1040 if (!enabled_str) {
1041 ret = -LTTNG_ERR_NOMEM;
1042 goto end;
1043 }
1044
1045 ret = parse_bool(enabled_str, &output->enabled);
1046 free(enabled_str);
1047 if (ret) {
1048 goto end;
1049 }
1050 } else {
1051 xmlNodePtr output_type_node;
1052
1053 /* destination */
1054 output_type_node = xmlFirstElementChild(node);
1055 if (!output_type_node) {
1056 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1057 goto end;
1058 }
1059
1060 if (!strcmp((const char *) output_type_node->name, config_element_path)) {
1061 /* path */
1062 output->path = (char *) xmlNodeGetContent(output_type_node);
1063 if (!output->path) {
1064 ret = -LTTNG_ERR_NOMEM;
1065 goto end;
1066 }
1067 } else {
1068 /* net_output */
1069 ret = get_net_output_uris(
1070 output_type_node, &output->control_uri, &output->data_uri);
1071 if (ret) {
1072 goto end;
1073 }
1074 }
1075 }
1076 }
1077 ret = 0;
1078
1079 end:
1080 if (ret) {
1081 free(output->path);
1082 free(output->control_uri);
1083 free(output->data_uri);
1084 memset(output, 0, sizeof(struct consumer_output));
1085 }
1086 return ret;
1087 }
1088
1089 static int create_snapshot_session(const char *session_name,
1090 xmlNodePtr output_node,
1091 const struct config_load_session_override_attr *overrides)
1092 {
1093 int ret = 0;
1094 enum lttng_error_code ret_code;
1095 xmlNodePtr node = nullptr;
1096 xmlNodePtr snapshot_output_list_node;
1097 xmlNodePtr snapshot_output_node;
1098 struct lttng_session_descriptor *session_descriptor = nullptr;
1099
1100 LTTNG_ASSERT(session_name);
1101 LTTNG_ASSERT(output_node);
1102
1103 /*
1104 * Use a descriptor without output since consumer output size is not
1105 * exposed by the session descriptor api.
1106 */
1107 session_descriptor = lttng_session_descriptor_snapshot_create(session_name);
1108 if (session_descriptor == nullptr) {
1109 ret = -LTTNG_ERR_NOMEM;
1110 goto end;
1111 }
1112
1113 ret_code = lttng_create_session_ext(session_descriptor);
1114 if (ret_code != LTTNG_OK) {
1115 ret = -ret_code;
1116 goto end;
1117 }
1118
1119 snapshot_output_list_node = xmlFirstElementChild(output_node);
1120
1121 /* Parse and create snapshot outputs */
1122 for (snapshot_output_node = xmlFirstElementChild(snapshot_output_list_node);
1123 snapshot_output_node;
1124 snapshot_output_node = xmlNextElementSibling(snapshot_output_node)) {
1125 char *name = nullptr;
1126 uint64_t max_size = UINT64_MAX;
1127 struct consumer_output output = {};
1128 struct lttng_snapshot_output *snapshot_output = nullptr;
1129 const char *control_uri = nullptr;
1130 const char *data_uri = nullptr;
1131 const char *path = nullptr;
1132
1133 for (node = xmlFirstElementChild(snapshot_output_node); node;
1134 node = xmlNextElementSibling(node)) {
1135 if (!strcmp((const char *) node->name, config_element_name)) {
1136 /* name */
1137 name = (char *) xmlNodeGetContent(node);
1138 if (!name) {
1139 ret = -LTTNG_ERR_NOMEM;
1140 goto error_snapshot_output;
1141 }
1142 } else if (!strcmp((const char *) node->name, config_element_max_size)) {
1143 xmlChar *content = xmlNodeGetContent(node);
1144
1145 /* max_size */
1146 if (!content) {
1147 ret = -LTTNG_ERR_NOMEM;
1148 goto error_snapshot_output;
1149 }
1150 ret = parse_uint(content, &max_size);
1151 free(content);
1152 if (ret) {
1153 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1154 goto error_snapshot_output;
1155 }
1156 } else {
1157 /* consumer_output */
1158 ret = process_consumer_output(node, &output);
1159 if (ret) {
1160 goto error_snapshot_output;
1161 }
1162 }
1163 }
1164
1165 control_uri = output.control_uri;
1166 data_uri = output.data_uri;
1167 path = output.path;
1168
1169 if (overrides) {
1170 if (overrides->path_url) {
1171 path = overrides->path_url;
1172 /* Control/data_uri are null */
1173 control_uri = nullptr;
1174 data_uri = nullptr;
1175 } else {
1176 if (overrides->ctrl_url) {
1177 control_uri = overrides->ctrl_url;
1178 /* path is null */
1179 path = nullptr;
1180 }
1181 if (overrides->data_url) {
1182 data_uri = overrides->data_url;
1183 /* path is null */
1184 path = nullptr;
1185 }
1186 }
1187 }
1188
1189 snapshot_output = lttng_snapshot_output_create();
1190 if (!snapshot_output) {
1191 ret = -LTTNG_ERR_NOMEM;
1192 goto error_snapshot_output;
1193 }
1194
1195 ret = lttng_snapshot_output_set_name(name, snapshot_output);
1196 if (ret) {
1197 goto error_snapshot_output;
1198 }
1199
1200 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1201 if (ret) {
1202 goto error_snapshot_output;
1203 }
1204
1205 if (path) {
1206 ret = lttng_snapshot_output_set_ctrl_url(path, snapshot_output);
1207 if (ret) {
1208 goto error_snapshot_output;
1209 }
1210 } else {
1211 if (control_uri) {
1212 ret = lttng_snapshot_output_set_ctrl_url(control_uri,
1213 snapshot_output);
1214 if (ret) {
1215 goto error_snapshot_output;
1216 }
1217 }
1218
1219 if (data_uri) {
1220 ret = lttng_snapshot_output_set_data_url(data_uri, snapshot_output);
1221 if (ret) {
1222 goto error_snapshot_output;
1223 }
1224 }
1225 }
1226
1227 ret = lttng_snapshot_add_output(session_name, snapshot_output);
1228 error_snapshot_output:
1229 free(name);
1230 free(output.path);
1231 free(output.control_uri);
1232 free(output.data_uri);
1233 lttng_snapshot_output_destroy(snapshot_output);
1234 if (ret) {
1235 goto end;
1236 }
1237 }
1238 end:
1239 lttng_session_descriptor_destroy(session_descriptor);
1240 return ret;
1241 }
1242
1243 static int create_session(const char *name,
1244 xmlNodePtr output_node,
1245 uint64_t live_timer_interval,
1246 const struct config_load_session_override_attr *overrides)
1247 {
1248 int ret = 0;
1249 enum lttng_error_code ret_code;
1250 struct consumer_output output = {};
1251 xmlNodePtr consumer_output_node;
1252 const char *control_uri = nullptr;
1253 const char *data_uri = nullptr;
1254 const char *path = nullptr;
1255 struct lttng_session_descriptor *session_descriptor = nullptr;
1256
1257 LTTNG_ASSERT(name);
1258
1259 if (output_node) {
1260 consumer_output_node = xmlFirstElementChild(output_node);
1261 if (!consumer_output_node) {
1262 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1263 goto end;
1264 }
1265
1266 if (strcmp((const char *) consumer_output_node->name,
1267 config_element_consumer_output) != 0) {
1268 WARN("Invalid output type, expected %s node",
1269 config_element_consumer_output);
1270 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1271 goto end;
1272 }
1273
1274 ret = process_consumer_output(consumer_output_node, &output);
1275 if (ret) {
1276 goto end;
1277 }
1278 }
1279
1280 control_uri = output.control_uri;
1281 data_uri = output.data_uri;
1282 path = output.path;
1283
1284 /* Check for override and apply them */
1285 if (overrides) {
1286 if (overrides->path_url) {
1287 path = overrides->path_url;
1288 /* control/data_uri are null */;
1289 control_uri = nullptr;
1290 data_uri = nullptr;
1291 } else {
1292 if (overrides->ctrl_url) {
1293 control_uri = overrides->ctrl_url;
1294 /* path is null */
1295 path = nullptr;
1296 }
1297 if (overrides->data_url) {
1298 data_uri = overrides->data_url;
1299 /* path is null */
1300 path = nullptr;
1301 }
1302 }
1303 }
1304
1305 if (live_timer_interval != UINT64_MAX && !control_uri && !data_uri) {
1306 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1307 goto end;
1308 }
1309
1310 if (control_uri || data_uri) {
1311 /* network destination */
1312 if (live_timer_interval && live_timer_interval != UINT64_MAX) {
1313 /*
1314 * URLs are provided for sure since the test above make sure that
1315 * with a live timer the data and control URIs are provided. So,
1316 * NULL is passed here and will be set right after.
1317 */
1318 session_descriptor = lttng_session_descriptor_live_network_create(
1319 name, control_uri, data_uri, live_timer_interval);
1320 } else {
1321 session_descriptor = lttng_session_descriptor_network_create(
1322 name, control_uri, data_uri);
1323 }
1324
1325 } else if (path != nullptr) {
1326 session_descriptor = lttng_session_descriptor_local_create(name, path);
1327 } else {
1328 /* No output */
1329 session_descriptor = lttng_session_descriptor_create(name);
1330 }
1331
1332 if (session_descriptor == nullptr) {
1333 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1334 goto end;
1335 }
1336
1337 ret_code = lttng_create_session_ext(session_descriptor);
1338 if (ret_code != LTTNG_OK) {
1339 ret = -ret_code;
1340 goto end;
1341 }
1342
1343 end:
1344 free(output.path);
1345 free(output.control_uri);
1346 free(output.data_uri);
1347 lttng_session_descriptor_destroy(session_descriptor);
1348 return ret;
1349 }
1350
1351 static struct lttng_userspace_probe_location *
1352 process_userspace_probe_function_attribute_node(xmlNodePtr attribute_node)
1353 {
1354 xmlNodePtr function_attribute_node;
1355 char *function_name = nullptr, *binary_path = nullptr;
1356 struct lttng_userspace_probe_location *location = nullptr;
1357 struct lttng_userspace_probe_location_lookup_method *lookup_method = nullptr;
1358
1359 /*
1360 * Process userspace probe location function attributes. The order of
1361 * the fields are not guaranteed so we need to iterate over all fields
1362 * and check at the end if everything we need for this location type is
1363 * there.
1364 */
1365 for (function_attribute_node = xmlFirstElementChild(attribute_node);
1366 function_attribute_node;
1367 function_attribute_node = xmlNextElementSibling(function_attribute_node)) {
1368 /* Handle function name, binary path and lookup method. */
1369 if (!strcmp((const char *) function_attribute_node->name,
1370 config_element_userspace_probe_function_location_function_name)) {
1371 function_name = (char *) xmlNodeGetContent(function_attribute_node);
1372 if (!function_name) {
1373 goto error;
1374 }
1375 } else if (!strcmp((const char *) function_attribute_node->name,
1376 config_element_userspace_probe_location_binary_path)) {
1377 binary_path = (char *) xmlNodeGetContent(function_attribute_node);
1378 if (!binary_path) {
1379 goto error;
1380 }
1381 } else if (!strcmp((const char *) function_attribute_node->name,
1382 config_element_userspace_probe_lookup)) {
1383 char *lookup_method_name;
1384
1385 lookup_method_name = (char *) xmlNodeGetContent(function_attribute_node);
1386 if (!lookup_method_name) {
1387 goto error;
1388 }
1389
1390 /*
1391 * function_default lookup method defaults to
1392 * function_elf lookup method at the moment.
1393 */
1394 if (!strcmp(lookup_method_name,
1395 config_element_userspace_probe_lookup_function_elf) ||
1396 !strcmp(lookup_method_name,
1397 config_element_userspace_probe_lookup_function_default)) {
1398 lookup_method =
1399 lttng_userspace_probe_location_lookup_method_function_elf_create();
1400 if (!lookup_method) {
1401 PERROR("Error creating function default/ELF lookup method");
1402 }
1403 } else {
1404 WARN("Unknown function lookup method");
1405 }
1406
1407 free(lookup_method_name);
1408 if (!lookup_method) {
1409 goto error;
1410 }
1411 } else {
1412 goto error;
1413 }
1414
1415 /* Check if all the necessary fields were found. */
1416 if (binary_path && function_name && lookup_method) {
1417 /* Ownership of lookup_method is transferred. */
1418 location = lttng_userspace_probe_location_function_create(
1419 binary_path, function_name, lookup_method);
1420 lookup_method = nullptr;
1421 goto error;
1422 }
1423 }
1424 error:
1425 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
1426 free(binary_path);
1427 free(function_name);
1428 return location;
1429 }
1430
1431 static struct lttng_userspace_probe_location *
1432 process_userspace_probe_tracepoint_attribute_node(xmlNodePtr attribute_node)
1433 {
1434 xmlNodePtr tracepoint_attribute_node;
1435 char *probe_name = nullptr, *provider_name = nullptr, *binary_path = nullptr;
1436 struct lttng_userspace_probe_location *location = nullptr;
1437 struct lttng_userspace_probe_location_lookup_method *lookup_method = nullptr;
1438
1439 /*
1440 * Process userspace probe location tracepoint attributes. The order of
1441 * the fields are not guaranteed so we need to iterate over all fields
1442 * and check at the end if everything we need for this location type is
1443 * there.
1444 */
1445 for (tracepoint_attribute_node = xmlFirstElementChild(attribute_node);
1446 tracepoint_attribute_node;
1447 tracepoint_attribute_node = xmlNextElementSibling(tracepoint_attribute_node)) {
1448 if (!strcmp((const char *) tracepoint_attribute_node->name,
1449 config_element_userspace_probe_tracepoint_location_probe_name)) {
1450 probe_name = (char *) xmlNodeGetContent(tracepoint_attribute_node);
1451 if (!probe_name) {
1452 goto error;
1453 }
1454 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1455 config_element_userspace_probe_tracepoint_location_provider_name)) {
1456 provider_name = (char *) xmlNodeGetContent(tracepoint_attribute_node);
1457 if (!provider_name) {
1458 goto error;
1459 }
1460 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1461 config_element_userspace_probe_location_binary_path)) {
1462 binary_path = (char *) xmlNodeGetContent(tracepoint_attribute_node);
1463 if (!binary_path) {
1464 goto error;
1465 }
1466 } else if (!strcmp((const char *) tracepoint_attribute_node->name,
1467 config_element_userspace_probe_lookup)) {
1468 char *lookup_method_name;
1469
1470 lookup_method_name = (char *) xmlNodeGetContent(tracepoint_attribute_node);
1471 if (!lookup_method_name) {
1472 goto error;
1473 }
1474
1475 if (!strcmp(lookup_method_name,
1476 config_element_userspace_probe_lookup_tracepoint_sdt)) {
1477 lookup_method =
1478 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1479 if (!lookup_method) {
1480 PERROR("Error creating tracepoint SDT lookup method");
1481 }
1482 } else {
1483 WARN("Unknown tracepoint lookup method");
1484 }
1485
1486 free(lookup_method_name);
1487 if (!lookup_method) {
1488 goto error;
1489 }
1490 } else {
1491 WARN("Unknown tracepoint attribute");
1492 goto error;
1493 }
1494
1495 /* Check if all the necessary fields were found. */
1496 if (binary_path && provider_name && probe_name && lookup_method) {
1497 /* Ownership of lookup_method is transferred. */
1498 location = lttng_userspace_probe_location_tracepoint_create(
1499 binary_path, provider_name, probe_name, lookup_method);
1500 lookup_method = nullptr;
1501 goto error;
1502 }
1503 }
1504 error:
1505 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
1506 free(binary_path);
1507 free(provider_name);
1508 free(probe_name);
1509 return location;
1510 }
1511
1512 static int process_probe_attribute_node(xmlNodePtr probe_attribute_node,
1513 struct lttng_event_probe_attr *attr)
1514 {
1515 int ret;
1516
1517 LTTNG_ASSERT(probe_attribute_node);
1518 LTTNG_ASSERT(attr);
1519
1520 if (!strcmp((const char *) probe_attribute_node->name, config_element_address)) {
1521 xmlChar *content;
1522 uint64_t addr = 0;
1523
1524 /* addr */
1525 content = xmlNodeGetContent(probe_attribute_node);
1526 if (!content) {
1527 ret = -LTTNG_ERR_NOMEM;
1528 goto end;
1529 }
1530
1531 ret = parse_uint(content, &addr);
1532 free(content);
1533 if (ret) {
1534 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1535 goto end;
1536 }
1537
1538 attr->addr = addr;
1539 } else if (!strcmp((const char *) probe_attribute_node->name, config_element_offset)) {
1540 xmlChar *content;
1541 uint64_t offset = 0;
1542
1543 /* offset */
1544 content = xmlNodeGetContent(probe_attribute_node);
1545 if (!content) {
1546 ret = -LTTNG_ERR_NOMEM;
1547 goto end;
1548 }
1549
1550 ret = parse_uint(content, &offset);
1551 free(content);
1552 if (ret) {
1553 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1554 goto end;
1555 }
1556
1557 attr->offset = offset;
1558 } else if (!strcmp((const char *) probe_attribute_node->name, config_element_symbol_name)) {
1559 xmlChar *content;
1560
1561 /* symbol_name */
1562 content = xmlNodeGetContent(probe_attribute_node);
1563 if (!content) {
1564 ret = -LTTNG_ERR_NOMEM;
1565 goto end;
1566 }
1567
1568 ret = lttng_strncpy(
1569 attr->symbol_name, (const char *) content, LTTNG_SYMBOL_NAME_LEN);
1570 if (ret == -1) {
1571 ERR("symbol name \"%s\"'s length (%zu) exceeds the maximal permitted length (%d) in session configuration",
1572 (const char *) content,
1573 strlen((const char *) content),
1574 LTTNG_SYMBOL_NAME_LEN);
1575 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1576 free(content);
1577 goto end;
1578 }
1579 free(content);
1580 }
1581 ret = 0;
1582 end:
1583 return ret;
1584 }
1585
1586 static int process_event_node(xmlNodePtr event_node,
1587 struct lttng_handle *handle,
1588 const char *channel_name,
1589 const enum process_event_node_phase phase)
1590 {
1591 int ret = 0, i;
1592 xmlNodePtr node;
1593 struct lttng_event *event;
1594 char **exclusions = nullptr;
1595 unsigned long exclusion_count = 0;
1596 char *filter_expression = nullptr;
1597
1598 LTTNG_ASSERT(event_node);
1599 LTTNG_ASSERT(handle);
1600 LTTNG_ASSERT(channel_name);
1601
1602 event = lttng_event_create();
1603 if (!event) {
1604 ret = -LTTNG_ERR_NOMEM;
1605 goto end;
1606 }
1607
1608 /* Initialize default log level which varies by domain */
1609 switch (handle->domain.type) {
1610 case LTTNG_DOMAIN_JUL:
1611 event->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
1612 break;
1613 case LTTNG_DOMAIN_LOG4J:
1614 event->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
1615 break;
1616 case LTTNG_DOMAIN_LOG4J2:
1617 event->loglevel = LTTNG_LOGLEVEL_LOG4J2_ALL;
1618 break;
1619 case LTTNG_DOMAIN_PYTHON:
1620 event->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
1621 break;
1622 case LTTNG_DOMAIN_UST:
1623 case LTTNG_DOMAIN_KERNEL:
1624 event->loglevel = LTTNG_LOGLEVEL_DEBUG;
1625 break;
1626 default:
1627 abort();
1628 }
1629
1630 for (node = xmlFirstElementChild(event_node); node; node = xmlNextElementSibling(node)) {
1631 if (!strcmp((const char *) node->name, config_element_name)) {
1632 xmlChar *content;
1633
1634 /* name */
1635 content = xmlNodeGetContent(node);
1636 if (!content) {
1637 ret = -LTTNG_ERR_NOMEM;
1638 goto end;
1639 }
1640
1641 ret = lttng_strncpy(
1642 event->name, (const char *) content, LTTNG_SYMBOL_NAME_LEN);
1643 if (ret == -1) {
1644 WARN("Event \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
1645 (const char *) content,
1646 strlen((const char *) content),
1647 LTTNG_SYMBOL_NAME_LEN);
1648 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1649 free(content);
1650 goto end;
1651 }
1652 free(content);
1653 } else if (!strcmp((const char *) node->name, config_element_enabled)) {
1654 xmlChar *content = xmlNodeGetContent(node);
1655
1656 /* enabled */
1657 if (!content) {
1658 ret = -LTTNG_ERR_NOMEM;
1659 goto end;
1660 }
1661
1662 ret = parse_bool(content, &event->enabled);
1663 free(content);
1664 if (ret) {
1665 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1666 goto end;
1667 }
1668 } else if (!strcmp((const char *) node->name, config_element_type)) {
1669 xmlChar *content = xmlNodeGetContent(node);
1670
1671 /* type */
1672 if (!content) {
1673 ret = -LTTNG_ERR_NOMEM;
1674 goto end;
1675 }
1676
1677 ret = get_event_type(content);
1678 free(content);
1679 if (ret < 0) {
1680 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1681 goto end;
1682 }
1683
1684 event->type = (lttng_event_type) ret;
1685 } else if (!strcmp((const char *) node->name, config_element_loglevel_type)) {
1686 xmlChar *content = xmlNodeGetContent(node);
1687
1688 /* loglevel_type */
1689 if (!content) {
1690 ret = -LTTNG_ERR_NOMEM;
1691 goto end;
1692 }
1693
1694 ret = get_loglevel_type(content);
1695 free(content);
1696 if (ret < 0) {
1697 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1698 goto end;
1699 }
1700
1701 event->loglevel_type = (lttng_loglevel_type) ret;
1702 } else if (!strcmp((const char *) node->name, config_element_loglevel)) {
1703 xmlChar *content;
1704 int64_t loglevel = 0;
1705
1706 /* loglevel */
1707 content = xmlNodeGetContent(node);
1708 if (!content) {
1709 ret = -LTTNG_ERR_NOMEM;
1710 goto end;
1711 }
1712
1713 ret = parse_int(content, &loglevel);
1714 free(content);
1715 if (ret) {
1716 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1717 goto end;
1718 }
1719
1720 if (loglevel > INT_MAX || loglevel < INT_MIN) {
1721 WARN("loglevel out of range.");
1722 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1723 goto end;
1724 }
1725
1726 event->loglevel = loglevel;
1727 } else if (!strcmp((const char *) node->name, config_element_filter)) {
1728 xmlChar *content = xmlNodeGetContent(node);
1729
1730 /* filter */
1731 if (!content) {
1732 ret = -LTTNG_ERR_NOMEM;
1733 goto end;
1734 }
1735
1736 free(filter_expression);
1737 filter_expression = strdup((char *) content);
1738 free(content);
1739 if (!filter_expression) {
1740 ret = -LTTNG_ERR_NOMEM;
1741 goto end;
1742 }
1743 } else if (!strcmp((const char *) node->name, config_element_exclusions)) {
1744 xmlNodePtr exclusion_node;
1745 int exclusion_index = 0;
1746
1747 /* exclusions */
1748 if (exclusions) {
1749 /*
1750 * Exclusions has already been initialized,
1751 * invalid file.
1752 */
1753 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1754 goto end;
1755 }
1756
1757 exclusion_count = xmlChildElementCount(node);
1758 if (!exclusion_count) {
1759 continue;
1760 }
1761
1762 exclusions = calloc<char *>(exclusion_count);
1763 if (!exclusions) {
1764 exclusion_count = 0;
1765 ret = -LTTNG_ERR_NOMEM;
1766 goto end;
1767 }
1768
1769 for (exclusion_node = xmlFirstElementChild(node); exclusion_node;
1770 exclusion_node = xmlNextElementSibling(exclusion_node)) {
1771 xmlChar *content = xmlNodeGetContent(exclusion_node);
1772
1773 if (!content) {
1774 ret = -LTTNG_ERR_NOMEM;
1775 goto end;
1776 }
1777
1778 exclusions[exclusion_index] = strdup((const char *) content);
1779 free(content);
1780 if (!exclusions[exclusion_index]) {
1781 ret = -LTTNG_ERR_NOMEM;
1782 goto end;
1783 }
1784 exclusion_index++;
1785 }
1786
1787 event->exclusion = 1;
1788 } else if (!strcmp((const char *) node->name, config_element_attributes)) {
1789 xmlNodePtr attribute_node = xmlFirstElementChild(node);
1790
1791 /* attributes */
1792 if (!attribute_node) {
1793 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1794 goto end;
1795 }
1796
1797 if (!strcmp((const char *) attribute_node->name,
1798 config_element_probe_attributes)) {
1799 xmlNodePtr probe_attribute_node;
1800
1801 /* probe_attributes */
1802 for (probe_attribute_node = xmlFirstElementChild(attribute_node);
1803 probe_attribute_node;
1804 probe_attribute_node =
1805 xmlNextElementSibling(probe_attribute_node)) {
1806 ret = process_probe_attribute_node(probe_attribute_node,
1807 &event->attr.probe);
1808 if (ret) {
1809 goto end;
1810 }
1811 }
1812 } else if (!strcmp((const char *) attribute_node->name,
1813 config_element_function_attributes)) {
1814 size_t sym_len;
1815 xmlChar *content;
1816 xmlNodePtr symbol_node = xmlFirstElementChild(attribute_node);
1817
1818 /* function_attributes */
1819 content = xmlNodeGetContent(symbol_node);
1820 if (!content) {
1821 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1822 goto end;
1823 }
1824
1825 sym_len = strlen((char *) content);
1826 if (sym_len >= LTTNG_SYMBOL_NAME_LEN) {
1827 WARN("Function name too long.");
1828 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1829 free(content);
1830 goto end;
1831 }
1832
1833 ret = lttng_strncpy(
1834 event->attr.ftrace.symbol_name, (char *) content, sym_len);
1835 if (ret == -1) {
1836 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1837 free(content);
1838 goto end;
1839 }
1840 free(content);
1841 } else if (!strcmp((const char *) attribute_node->name,
1842 config_element_userspace_probe_tracepoint_attributes)) {
1843 struct lttng_userspace_probe_location *location;
1844
1845 location = process_userspace_probe_tracepoint_attribute_node(
1846 attribute_node);
1847 if (!location) {
1848 WARN("Error processing userspace probe tracepoint attribute");
1849 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1850 goto end;
1851 }
1852 ret = lttng_event_set_userspace_probe_location(event, location);
1853 if (ret) {
1854 WARN("Error setting userspace probe location field");
1855 lttng_userspace_probe_location_destroy(location);
1856 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1857 goto end;
1858 }
1859 } else if (!strcmp((const char *) attribute_node->name,
1860 config_element_userspace_probe_function_attributes)) {
1861 struct lttng_userspace_probe_location *location;
1862
1863 location = process_userspace_probe_function_attribute_node(
1864 attribute_node);
1865 if (!location) {
1866 WARN("Error processing userspace probe function attribute");
1867 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1868 goto end;
1869 }
1870
1871 ret = lttng_event_set_userspace_probe_location(event, location);
1872 if (ret) {
1873 WARN("Error setting userspace probe location field");
1874 lttng_userspace_probe_location_destroy(location);
1875 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1876 goto end;
1877 }
1878 } else {
1879 /* Unknown event attribute. */
1880 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1881 goto end;
1882 }
1883 }
1884 }
1885
1886 if ((event->enabled && phase == ENABLE) || phase == CREATION) {
1887 ret = lttng_enable_event_with_exclusions(
1888 handle, event, channel_name, filter_expression, exclusion_count, exclusions);
1889 if (ret < 0) {
1890 WARN("Enabling event (name:%s) on load failed.", event->name);
1891 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1892 goto end;
1893 }
1894 }
1895 ret = 0;
1896 end:
1897 for (i = 0; i < exclusion_count; i++) {
1898 free(exclusions[i]);
1899 }
1900
1901 lttng_event_destroy(event);
1902 free(exclusions);
1903 free(filter_expression);
1904 return ret;
1905 }
1906
1907 static int
1908 process_events_node(xmlNodePtr events_node, struct lttng_handle *handle, const char *channel_name)
1909 {
1910 int ret = 0;
1911 struct lttng_event event;
1912 xmlNodePtr node;
1913
1914 LTTNG_ASSERT(events_node);
1915 LTTNG_ASSERT(handle);
1916 LTTNG_ASSERT(channel_name);
1917
1918 for (node = xmlFirstElementChild(events_node); node; node = xmlNextElementSibling(node)) {
1919 ret = process_event_node(node, handle, channel_name, CREATION);
1920 if (ret) {
1921 goto end;
1922 }
1923 }
1924
1925 /*
1926 * Disable all events to enable only the necessary events.
1927 * Limitations regarding lttng_disable_events and tuple descriptor
1928 * force this approach.
1929 */
1930 memset(&event, 0, sizeof(event));
1931 event.loglevel = -1;
1932 event.type = LTTNG_EVENT_ALL;
1933 ret = lttng_disable_event_ext(handle, &event, channel_name, nullptr);
1934 if (ret) {
1935 goto end;
1936 }
1937
1938 for (node = xmlFirstElementChild(events_node); node; node = xmlNextElementSibling(node)) {
1939 ret = process_event_node(node, handle, channel_name, ENABLE);
1940 if (ret) {
1941 goto end;
1942 }
1943 }
1944
1945 end:
1946 return ret;
1947 }
1948
1949 static int process_channel_attr_node(xmlNodePtr attr_node,
1950 struct lttng_channel *channel,
1951 xmlNodePtr *contexts_node,
1952 xmlNodePtr *events_node)
1953 {
1954 int ret;
1955
1956 LTTNG_ASSERT(attr_node);
1957 LTTNG_ASSERT(channel);
1958 LTTNG_ASSERT(contexts_node);
1959 LTTNG_ASSERT(events_node);
1960
1961 if (!strcmp((const char *) attr_node->name, config_element_name)) {
1962 xmlChar *content;
1963
1964 /* name */
1965 content = xmlNodeGetContent(attr_node);
1966 if (!content) {
1967 ret = -LTTNG_ERR_NOMEM;
1968 goto end;
1969 }
1970
1971 ret = lttng_strncpy(channel->name, (const char *) content, LTTNG_SYMBOL_NAME_LEN);
1972 if (ret == -1) {
1973 WARN("Channel \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
1974 (const char *) content,
1975 strlen((const char *) content),
1976 LTTNG_SYMBOL_NAME_LEN);
1977 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1978 free(content);
1979 goto end;
1980 }
1981 free(content);
1982 } else if (!strcmp((const char *) attr_node->name, config_element_enabled)) {
1983 xmlChar *content;
1984 int enabled;
1985
1986 /* enabled */
1987 content = xmlNodeGetContent(attr_node);
1988 if (!content) {
1989 ret = -LTTNG_ERR_NOMEM;
1990 goto end;
1991 }
1992
1993 ret = parse_bool(content, &enabled);
1994 free(content);
1995 if (ret) {
1996 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
1997 goto end;
1998 }
1999
2000 channel->enabled = enabled;
2001 } else if (!strcmp((const char *) attr_node->name, config_element_overwrite_mode)) {
2002 xmlChar *content;
2003
2004 /* overwrite_mode */
2005 content = xmlNodeGetContent(attr_node);
2006 if (!content) {
2007 ret = -LTTNG_ERR_NOMEM;
2008 goto end;
2009 }
2010
2011 ret = get_overwrite_mode(content);
2012 free(content);
2013 if (ret < 0) {
2014 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2015 goto end;
2016 }
2017
2018 channel->attr.overwrite = ret;
2019 } else if (!strcmp((const char *) attr_node->name, config_element_subbuf_size)) {
2020 xmlChar *content;
2021
2022 /* subbuffer_size */
2023 content = xmlNodeGetContent(attr_node);
2024 if (!content) {
2025 ret = -LTTNG_ERR_NOMEM;
2026 goto end;
2027 }
2028
2029 ret = parse_uint(content, &channel->attr.subbuf_size);
2030 free(content);
2031 if (ret) {
2032 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2033 goto end;
2034 }
2035 } else if (!strcmp((const char *) attr_node->name, config_element_num_subbuf)) {
2036 xmlChar *content;
2037
2038 /* subbuffer_count */
2039 content = xmlNodeGetContent(attr_node);
2040 if (!content) {
2041 ret = -LTTNG_ERR_NOMEM;
2042 goto end;
2043 }
2044
2045 ret = parse_uint(content, &channel->attr.num_subbuf);
2046 free(content);
2047 if (ret) {
2048 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2049 goto end;
2050 }
2051 } else if (!strcmp((const char *) attr_node->name, config_element_switch_timer_interval)) {
2052 xmlChar *content;
2053 uint64_t switch_timer_interval = 0;
2054
2055 /* switch_timer_interval */
2056 content = xmlNodeGetContent(attr_node);
2057 if (!content) {
2058 ret = -LTTNG_ERR_NOMEM;
2059 goto end;
2060 }
2061
2062 ret = parse_uint(content, &switch_timer_interval);
2063 free(content);
2064 if (ret) {
2065 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2066 goto end;
2067 }
2068
2069 if (switch_timer_interval > UINT_MAX) {
2070 WARN("switch_timer_interval out of range.");
2071 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2072 goto end;
2073 }
2074
2075 channel->attr.switch_timer_interval = switch_timer_interval;
2076 } else if (!strcmp((const char *) attr_node->name, config_element_read_timer_interval)) {
2077 xmlChar *content;
2078 uint64_t read_timer_interval = 0;
2079
2080 /* read_timer_interval */
2081 content = xmlNodeGetContent(attr_node);
2082 if (!content) {
2083 ret = -LTTNG_ERR_NOMEM;
2084 goto end;
2085 }
2086
2087 ret = parse_uint(content, &read_timer_interval);
2088 free(content);
2089 if (ret) {
2090 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2091 goto end;
2092 }
2093
2094 if (read_timer_interval > UINT_MAX) {
2095 WARN("read_timer_interval out of range.");
2096 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2097 goto end;
2098 }
2099
2100 channel->attr.read_timer_interval = read_timer_interval;
2101 } else if (!strcmp((const char *) attr_node->name, config_element_output_type)) {
2102 xmlChar *content;
2103
2104 /* output_type */
2105 content = xmlNodeGetContent(attr_node);
2106 if (!content) {
2107 ret = -LTTNG_ERR_NOMEM;
2108 goto end;
2109 }
2110
2111 ret = get_output_type(content);
2112 free(content);
2113 if (ret < 0) {
2114 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2115 goto end;
2116 }
2117
2118 channel->attr.output = (lttng_event_output) ret;
2119 } else if (!strcmp((const char *) attr_node->name, config_element_tracefile_size)) {
2120 xmlChar *content;
2121
2122 /* tracefile_size */
2123 content = xmlNodeGetContent(attr_node);
2124 if (!content) {
2125 ret = -LTTNG_ERR_NOMEM;
2126 goto end;
2127 }
2128
2129 ret = parse_uint(content, &channel->attr.tracefile_size);
2130 free(content);
2131 if (ret) {
2132 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2133 goto end;
2134 }
2135 } else if (!strcmp((const char *) attr_node->name, config_element_tracefile_count)) {
2136 xmlChar *content;
2137
2138 /* tracefile_count */
2139 content = xmlNodeGetContent(attr_node);
2140 if (!content) {
2141 ret = -LTTNG_ERR_NOMEM;
2142 goto end;
2143 }
2144
2145 ret = parse_uint(content, &channel->attr.tracefile_count);
2146 free(content);
2147 if (ret) {
2148 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2149 goto end;
2150 }
2151 } else if (!strcmp((const char *) attr_node->name, config_element_live_timer_interval)) {
2152 xmlChar *content;
2153 uint64_t live_timer_interval = 0;
2154
2155 /* live_timer_interval */
2156 content = xmlNodeGetContent(attr_node);
2157 if (!content) {
2158 ret = -LTTNG_ERR_NOMEM;
2159 goto end;
2160 }
2161
2162 ret = parse_uint(content, &live_timer_interval);
2163 free(content);
2164 if (ret) {
2165 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2166 goto end;
2167 }
2168
2169 if (live_timer_interval > UINT_MAX) {
2170 WARN("live_timer_interval out of range.");
2171 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2172 goto end;
2173 }
2174
2175 channel->attr.live_timer_interval = live_timer_interval;
2176 } else if (!strcmp((const char *) attr_node->name, config_element_monitor_timer_interval)) {
2177 xmlChar *content;
2178 uint64_t monitor_timer_interval = 0;
2179
2180 /* monitor_timer_interval */
2181 content = xmlNodeGetContent(attr_node);
2182 if (!content) {
2183 ret = -LTTNG_ERR_NOMEM;
2184 goto end;
2185 }
2186
2187 ret = parse_uint(content, &monitor_timer_interval);
2188 free(content);
2189 if (ret) {
2190 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2191 goto end;
2192 }
2193
2194 ret = lttng_channel_set_monitor_timer_interval(channel, monitor_timer_interval);
2195 if (ret) {
2196 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2197 goto end;
2198 }
2199 } else if (!strcmp((const char *) attr_node->name, config_element_blocking_timeout)) {
2200 xmlChar *content;
2201 int64_t blocking_timeout = 0;
2202
2203 /* blocking_timeout */
2204 content = xmlNodeGetContent(attr_node);
2205 if (!content) {
2206 ret = -LTTNG_ERR_NOMEM;
2207 goto end;
2208 }
2209
2210 ret = parse_int(content, &blocking_timeout);
2211 free(content);
2212 if (ret) {
2213 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2214 goto end;
2215 }
2216
2217 ret = lttng_channel_set_blocking_timeout(channel, blocking_timeout);
2218 if (ret) {
2219 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2220 goto end;
2221 }
2222 } else if (!strcmp((const char *) attr_node->name, config_element_events)) {
2223 /* events */
2224 *events_node = attr_node;
2225 } else {
2226 /* contexts */
2227 *contexts_node = attr_node;
2228 }
2229 ret = 0;
2230 end:
2231 return ret;
2232 }
2233
2234 static int
2235 process_context_node(xmlNodePtr context_node, struct lttng_handle *handle, const char *channel_name)
2236 {
2237 int ret;
2238 struct lttng_event_context context;
2239 xmlNodePtr context_child_node = xmlFirstElementChild(context_node);
2240
2241 LTTNG_ASSERT(handle);
2242 LTTNG_ASSERT(channel_name);
2243
2244 if (!context_child_node) {
2245 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2246 goto end;
2247 }
2248
2249 memset(&context, 0, sizeof(context));
2250
2251 if (!strcmp((const char *) context_child_node->name, config_element_type)) {
2252 /* type */
2253 xmlChar *content = xmlNodeGetContent(context_child_node);
2254
2255 if (!content) {
2256 ret = -LTTNG_ERR_NOMEM;
2257 goto end;
2258 }
2259
2260 ret = get_context_type(content);
2261 free(content);
2262 if (ret < 0) {
2263 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2264 goto end;
2265 }
2266
2267 context.ctx = (lttng_event_context_type) ret;
2268 } else if (!strcmp((const char *) context_child_node->name, config_element_context_perf)) {
2269 /* perf */
2270 xmlNodePtr perf_attr_node;
2271
2272 context.ctx = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
2273 LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER :
2274 LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER;
2275 for (perf_attr_node = xmlFirstElementChild(context_child_node); perf_attr_node;
2276 perf_attr_node = xmlNextElementSibling(perf_attr_node)) {
2277 if (!strcmp((const char *) perf_attr_node->name, config_element_type)) {
2278 xmlChar *content;
2279 uint64_t type = 0;
2280
2281 /* type */
2282 content = xmlNodeGetContent(perf_attr_node);
2283 if (!content) {
2284 ret = -LTTNG_ERR_NOMEM;
2285 goto end;
2286 }
2287
2288 ret = parse_uint(content, &type);
2289 free(content);
2290 if (ret) {
2291 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2292 goto end;
2293 }
2294
2295 if (type > UINT32_MAX) {
2296 WARN("perf context type out of range.");
2297 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2298 goto end;
2299 }
2300
2301 context.u.perf_counter.type = type;
2302 } else if (!strcmp((const char *) perf_attr_node->name,
2303 config_element_config)) {
2304 xmlChar *content;
2305 uint64_t config = 0;
2306
2307 /* config */
2308 content = xmlNodeGetContent(perf_attr_node);
2309 if (!content) {
2310 ret = -LTTNG_ERR_NOMEM;
2311 goto end;
2312 }
2313
2314 ret = parse_uint(content, &config);
2315 free(content);
2316 if (ret) {
2317 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2318 goto end;
2319 }
2320
2321 context.u.perf_counter.config = config;
2322 } else if (!strcmp((const char *) perf_attr_node->name,
2323 config_element_name)) {
2324 xmlChar *content;
2325
2326 /* name */
2327 content = xmlNodeGetContent(perf_attr_node);
2328 if (!content) {
2329 ret = -LTTNG_ERR_NOMEM;
2330 goto end;
2331 }
2332
2333 ret = lttng_strncpy(context.u.perf_counter.name,
2334 (const char *) content,
2335 LTTNG_SYMBOL_NAME_LEN);
2336 if (ret == -1) {
2337 WARN("Perf counter \"%s\"'s name length (%zu) exceeds the maximal permitted length (%d) in session configuration",
2338 (const char *) content,
2339 strlen((const char *) content),
2340 LTTNG_SYMBOL_NAME_LEN);
2341 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2342 free(content);
2343 goto end;
2344 }
2345 free(content);
2346 }
2347 }
2348 } else if (!strcmp((const char *) context_child_node->name, config_element_context_app)) {
2349 /* application context */
2350 xmlNodePtr app_ctx_node;
2351
2352 context.ctx = LTTNG_EVENT_CONTEXT_APP_CONTEXT;
2353 for (app_ctx_node = xmlFirstElementChild(context_child_node); app_ctx_node;
2354 app_ctx_node = xmlNextElementSibling(app_ctx_node)) {
2355 xmlChar *content;
2356 char **target = strcmp((const char *) app_ctx_node->name,
2357 config_element_context_app_provider_name) == 0 ?
2358 &context.u.app_ctx.provider_name :
2359 &context.u.app_ctx.ctx_name;
2360
2361 content = xmlNodeGetContent(app_ctx_node);
2362 if (!content) {
2363 ret = -LTTNG_ERR_NOMEM;
2364 goto end;
2365 }
2366
2367 *target = (char *) content;
2368 }
2369 } else {
2370 /* Unrecognized context type */
2371 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2372 goto end;
2373 }
2374
2375 ret = lttng_add_context(handle, &context, nullptr, channel_name);
2376 if (context.ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
2377 free(context.u.app_ctx.provider_name);
2378 free(context.u.app_ctx.ctx_name);
2379 }
2380 end:
2381 return ret;
2382 }
2383
2384 static int process_contexts_node(xmlNodePtr contexts_node,
2385 struct lttng_handle *handle,
2386 const char *channel_name)
2387 {
2388 int ret = 0;
2389 xmlNodePtr context_node;
2390
2391 for (context_node = xmlFirstElementChild(contexts_node); context_node;
2392 context_node = xmlNextElementSibling(context_node)) {
2393 ret = process_context_node(context_node, handle, channel_name);
2394 if (ret) {
2395 goto end;
2396 }
2397 }
2398 end:
2399 return ret;
2400 }
2401
2402 static int get_tracker_elements(enum lttng_process_attr process_attr,
2403 const char **element_id_tracker,
2404 const char **element_value_type,
2405 const char **element_value,
2406 const char **element_value_alias,
2407 const char **element_name)
2408 {
2409 int ret = 0;
2410
2411 switch (process_attr) {
2412 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2413 *element_id_tracker = config_element_process_attr_tracker_pid;
2414 *element_value_type = config_element_process_attr_pid_value;
2415 *element_value = config_element_process_attr_id;
2416 *element_value_alias = config_element_process_attr_id;
2417 *element_name = nullptr;
2418 break;
2419 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2420 *element_id_tracker = config_element_process_attr_tracker_vpid;
2421 *element_value_type = config_element_process_attr_vpid_value;
2422 *element_value = config_element_process_attr_id;
2423 *element_value_alias = nullptr;
2424 *element_name = nullptr;
2425 break;
2426 case LTTNG_PROCESS_ATTR_USER_ID:
2427 *element_id_tracker = config_element_process_attr_tracker_uid;
2428 *element_value_type = config_element_process_attr_uid_value;
2429 *element_value = config_element_process_attr_id;
2430 *element_value_alias = nullptr;
2431 *element_name = config_element_name;
2432 break;
2433 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2434 *element_id_tracker = config_element_process_attr_tracker_vuid;
2435 *element_value_type = config_element_process_attr_vuid_value;
2436 *element_value = config_element_process_attr_id;
2437 *element_value_alias = nullptr;
2438 *element_name = config_element_name;
2439 break;
2440 case LTTNG_PROCESS_ATTR_GROUP_ID:
2441 *element_id_tracker = config_element_process_attr_tracker_gid;
2442 *element_value_type = config_element_process_attr_gid_value;
2443 *element_value = config_element_process_attr_id;
2444 *element_value_alias = nullptr;
2445 *element_name = config_element_name;
2446 break;
2447 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2448 *element_id_tracker = config_element_process_attr_tracker_vgid;
2449 *element_value_type = config_element_process_attr_vgid_value;
2450 *element_value = config_element_process_attr_id;
2451 *element_value_alias = nullptr;
2452 *element_name = config_element_name;
2453 break;
2454 default:
2455 ret = LTTNG_ERR_INVALID;
2456 }
2457 return ret;
2458 }
2459
2460 static int process_legacy_pid_tracker_node(xmlNodePtr trackers_node, struct lttng_handle *handle)
2461 {
2462 int ret = 0, child_count;
2463 xmlNodePtr targets_node = nullptr;
2464 xmlNodePtr node;
2465 const char *element_id_tracker;
2466 const char *element_target_id;
2467 const char *element_id;
2468 const char *element_id_alias;
2469 const char *element_name;
2470 enum lttng_error_code tracker_handle_ret_code;
2471 struct lttng_process_attr_tracker_handle *tracker_handle = nullptr;
2472 enum lttng_process_attr_tracker_handle_status status;
2473 const enum lttng_process_attr process_attr = handle->domain.type == LTTNG_DOMAIN_UST ?
2474 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID :
2475 LTTNG_PROCESS_ATTR_PROCESS_ID;
2476
2477 LTTNG_ASSERT(handle);
2478
2479 tracker_handle_ret_code = lttng_session_get_tracker_handle(
2480 handle->session_name, handle->domain.type, process_attr, &tracker_handle);
2481 if (tracker_handle_ret_code != LTTNG_OK) {
2482 ret = LTTNG_ERR_INVALID;
2483 goto end;
2484 }
2485
2486 ret = get_tracker_elements(process_attr,
2487 &element_id_tracker,
2488 &element_target_id,
2489 &element_id,
2490 &element_id_alias,
2491 &element_name);
2492 if (ret) {
2493 goto end;
2494 }
2495
2496 /* Get the targets node */
2497 for (node = xmlFirstElementChild(trackers_node); node; node = xmlNextElementSibling(node)) {
2498 if (!strcmp((const char *) node->name, config_element_tracker_targets_legacy)) {
2499 targets_node = node;
2500 break;
2501 }
2502 }
2503
2504 if (!targets_node) {
2505 ret = LTTNG_ERR_INVALID;
2506 goto end;
2507 }
2508
2509 /* Go through all id target node */
2510 child_count = xmlChildElementCount(targets_node);
2511 status = lttng_process_attr_tracker_handle_set_tracking_policy(
2512 tracker_handle,
2513 child_count == 0 ? LTTNG_TRACKING_POLICY_EXCLUDE_ALL :
2514 LTTNG_TRACKING_POLICY_INCLUDE_SET);
2515 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
2516 ret = LTTNG_ERR_UNK;
2517 goto end;
2518 }
2519
2520 /* Add all tracked values. */
2521 for (node = xmlFirstElementChild(targets_node); node; node = xmlNextElementSibling(node)) {
2522 xmlNodePtr pid_target_node = node;
2523
2524 /* get pid_target node and track it */
2525 for (node = xmlFirstElementChild(pid_target_node); node;
2526 node = xmlNextElementSibling(node)) {
2527 if (!strcmp((const char *) node->name, config_element_tracker_pid_legacy)) {
2528 int64_t id;
2529 xmlChar *content = xmlNodeGetContent(node);
2530
2531 if (!content) {
2532 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2533 goto end;
2534 }
2535
2536 ret = parse_int(content, &id);
2537 free(content);
2538 if (ret) {
2539 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2540 goto end;
2541 }
2542
2543 switch (process_attr) {
2544 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2545 status =
2546 lttng_process_attr_process_id_tracker_handle_add_pid(
2547 tracker_handle, (pid_t) id);
2548 break;
2549 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2550 status =
2551 lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
2552 tracker_handle, (pid_t) id);
2553 break;
2554 default:
2555 ret = LTTNG_ERR_INVALID;
2556 goto end;
2557 }
2558 }
2559 switch (status) {
2560 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
2561 continue;
2562 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID:
2563 ret = LTTNG_ERR_INVALID;
2564 break;
2565 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
2566 ret = LTTNG_ERR_PROCESS_ATTR_EXISTS;
2567 break;
2568 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
2569 ret = LTTNG_ERR_PROCESS_ATTR_MISSING;
2570 break;
2571 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
2572 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
2573 default:
2574 ret = LTTNG_ERR_UNK;
2575 goto end;
2576 }
2577 }
2578 node = pid_target_node;
2579 }
2580
2581 end:
2582 lttng_process_attr_tracker_handle_destroy(tracker_handle);
2583 return ret;
2584 }
2585
2586 static int process_id_tracker_node(xmlNodePtr id_tracker_node,
2587 struct lttng_handle *handle,
2588 enum lttng_process_attr process_attr)
2589 {
2590 int ret = 0, child_count;
2591 xmlNodePtr values_node = nullptr;
2592 xmlNodePtr node;
2593 const char *element_id_tracker;
2594 const char *element_target_id;
2595 const char *element_id;
2596 const char *element_id_alias;
2597 const char *element_name;
2598 enum lttng_error_code tracker_handle_ret_code;
2599 struct lttng_process_attr_tracker_handle *tracker_handle = nullptr;
2600 enum lttng_process_attr_tracker_handle_status status;
2601
2602 LTTNG_ASSERT(handle);
2603 LTTNG_ASSERT(id_tracker_node);
2604
2605 tracker_handle_ret_code = lttng_session_get_tracker_handle(
2606 handle->session_name, handle->domain.type, process_attr, &tracker_handle);
2607 if (tracker_handle_ret_code != LTTNG_OK) {
2608 ret = LTTNG_ERR_INVALID;
2609 goto end;
2610 }
2611
2612 ret = get_tracker_elements(process_attr,
2613 &element_id_tracker,
2614 &element_target_id,
2615 &element_id,
2616 &element_id_alias,
2617 &element_name);
2618 if (ret) {
2619 goto end;
2620 }
2621
2622 /* get the values node */
2623 for (node = xmlFirstElementChild(id_tracker_node); node;
2624 node = xmlNextElementSibling(node)) {
2625 if (!strcmp((const char *) node->name, config_element_process_attr_values)) {
2626 values_node = node;
2627 break;
2628 }
2629 }
2630
2631 if (!values_node) {
2632 ret = LTTNG_ERR_INVALID;
2633 goto end;
2634 }
2635
2636 /* Go through all id target node */
2637 child_count = xmlChildElementCount(values_node);
2638 status = lttng_process_attr_tracker_handle_set_tracking_policy(
2639 tracker_handle,
2640 child_count == 0 ? LTTNG_TRACKING_POLICY_EXCLUDE_ALL :
2641 LTTNG_TRACKING_POLICY_INCLUDE_SET);
2642 if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
2643 ret = LTTNG_ERR_UNK;
2644 goto end;
2645 }
2646
2647 /* Add all tracked values. */
2648 for (node = xmlFirstElementChild(values_node); node; node = xmlNextElementSibling(node)) {
2649 xmlNodePtr id_target_node = node;
2650
2651 /* get id node and track it */
2652 for (node = xmlFirstElementChild(id_target_node); node;
2653 node = xmlNextElementSibling(node)) {
2654 if (!strcmp((const char *) node->name, element_id) ||
2655 (element_id_alias &&
2656 !strcmp((const char *) node->name, element_id_alias))) {
2657 int64_t id;
2658 xmlChar *content = xmlNodeGetContent(node);
2659
2660 if (!content) {
2661 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2662 goto end;
2663 }
2664
2665 ret = parse_int(content, &id);
2666 free(content);
2667 if (ret) {
2668 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2669 goto end;
2670 }
2671
2672 switch (process_attr) {
2673 case LTTNG_PROCESS_ATTR_PROCESS_ID:
2674 status =
2675 lttng_process_attr_process_id_tracker_handle_add_pid(
2676 tracker_handle, (pid_t) id);
2677 break;
2678 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
2679 status =
2680 lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
2681 tracker_handle, (pid_t) id);
2682 break;
2683 case LTTNG_PROCESS_ATTR_USER_ID:
2684 status = lttng_process_attr_user_id_tracker_handle_add_uid(
2685 tracker_handle, (uid_t) id);
2686 break;
2687 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2688 status =
2689 lttng_process_attr_virtual_user_id_tracker_handle_add_uid(
2690 tracker_handle, (uid_t) id);
2691 break;
2692 case LTTNG_PROCESS_ATTR_GROUP_ID:
2693 status = lttng_process_attr_group_id_tracker_handle_add_gid(
2694 tracker_handle, (gid_t) id);
2695 break;
2696 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2697 status =
2698 lttng_process_attr_virtual_group_id_tracker_handle_add_gid(
2699 tracker_handle, (gid_t) id);
2700 break;
2701 default:
2702 ret = LTTNG_ERR_INVALID;
2703 goto end;
2704 }
2705 } else if (element_name &&
2706 !strcmp((const char *) node->name, element_name)) {
2707 xmlChar *content = xmlNodeGetContent(node);
2708
2709 if (!content) {
2710 ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
2711 goto end;
2712 }
2713
2714 switch (process_attr) {
2715 case LTTNG_PROCESS_ATTR_USER_ID:
2716 status =
2717 lttng_process_attr_user_id_tracker_handle_add_user_name(
2718 tracker_handle, (const char *) content);
2719 break;
2720 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
2721 status =
2722 lttng_process_attr_virtual_user_id_tracker_handle_add_user_name(
2723 tracker_handle, (const char *) content);
2724 break;
2725 case LTTNG_PROCESS_ATTR_GROUP_ID:
2726 status =
2727 lttng_process_attr_group_id_tracker_handle_add_group_name(
2728 tracker_handle, (const char *) content);
2729 break;
2730 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
2731 status =
2732 lttng_process_attr_virtual_group_id_tracker_handle_add_group_name(
2733 tracker_handle, (const char *) content);
2734 break;
2735 default:
2736 free(content);
2737 ret = LTTNG_ERR_INVALID;
2738 goto end;
2739 }
2740 free(content);
2741 }
2742 switch (status) {
2743 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
2744 continue;
2745 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID:
2746 ret = LTTNG_ERR_INVALID;
2747 break;
2748 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
2749 ret = LTTNG_ERR_PROCESS_ATTR_EXISTS;
2750 break;
2751 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
2752 ret = LTTNG_ERR_PROCESS_ATTR_MISSING;
2753 break;
2754 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
2755 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
2756 default:
2757 ret = LTTNG_ERR_UNK;
2758 goto end;
2759 }
2760 }
2761 node = id_target_node;
2762 }
2763
2764 end:
2765 lttng_process_attr_tracker_handle_destroy(tracker_handle);
2766 return ret;
2767 }
2768
2769 static int process_domain_node(xmlNodePtr domain_node, const char *session_name)
2770 {
2771 int ret;
2772 struct lttng_domain domain {};
2773 struct lttng_handle *handle = nullptr;
2774 struct lttng_channel *channel = nullptr;
2775 xmlNodePtr channels_node = nullptr;
2776 xmlNodePtr trackers_node = nullptr;
2777 xmlNodePtr pid_tracker_node = nullptr;
2778 xmlNodePtr vpid_tracker_node = nullptr;
2779 xmlNodePtr uid_tracker_node = nullptr;
2780 xmlNodePtr vuid_tracker_node = nullptr;
2781 xmlNodePtr gid_tracker_node = nullptr;
2782 xmlNodePtr vgid_tracker_node = nullptr;
2783 xmlNodePtr node;
2784
2785 LTTNG_ASSERT(session_name);
2786
2787 ret = init_domain(domain_node, &domain);
2788 if (ret) {
2789 goto end;
2790 }
2791
2792 handle = lttng_create_handle(session_name, &domain);
2793 if (!handle) {
2794 ret = -LTTNG_ERR_NOMEM;
2795 goto end;
2796 }
2797
2798 /* get the channels node */
2799 for (node = xmlFirstElementChild(domain_node); node; node = xmlNextElementSibling(node)) {
2800 if (!strcmp((const char *) node->name, config_element_channels)) {
2801 channels_node = node;
2802 break;
2803 }
2804 }
2805
2806 if (!channels_node) {
2807 goto end;
2808 }
2809
2810 /* create all channels */
2811 for (node = xmlFirstElementChild(channels_node); node; node = xmlNextElementSibling(node)) {
2812 const enum lttng_domain_type original_domain = domain.type;
2813 xmlNodePtr contexts_node = nullptr;
2814 xmlNodePtr events_node = nullptr;
2815 xmlNodePtr channel_attr_node;
2816
2817 /*
2818 * Channels of the "agent" types cannot be created directly.
2819 * They are meant to be created implicitly through the
2820 * activation of events in their domain. However, a user
2821 * can override the default channel configuration attributes
2822 * by creating the underlying UST channel _before_ enabling
2823 * an agent domain event.
2824 *
2825 * Hence, the channel's type is substituted before the creation
2826 * and restored by the time the events are created.
2827 */
2828 switch (domain.type) {
2829 case LTTNG_DOMAIN_JUL:
2830 case LTTNG_DOMAIN_LOG4J:
2831 case LTTNG_DOMAIN_LOG4J2:
2832 case LTTNG_DOMAIN_PYTHON:
2833 domain.type = LTTNG_DOMAIN_UST;
2834 default:
2835 break;
2836 }
2837
2838 channel = lttng_channel_create(&domain);
2839 if (!channel) {
2840 ret = -1;
2841 goto end;
2842 }
2843
2844 for (channel_attr_node = xmlFirstElementChild(node); channel_attr_node;
2845 channel_attr_node = xmlNextElementSibling(channel_attr_node)) {
2846 ret = process_channel_attr_node(
2847 channel_attr_node, channel, &contexts_node, &events_node);
2848 if (ret) {
2849 goto end;
2850 }
2851 }
2852
2853 ret = lttng_enable_channel(handle, channel);
2854 if (ret < 0) {
2855 goto end;
2856 }
2857
2858 /* Restore the original channel domain. */
2859 domain.type = original_domain;
2860
2861 ret = process_events_node(events_node, handle, channel->name);
2862 if (ret) {
2863 goto end;
2864 }
2865
2866 ret = process_contexts_node(contexts_node, handle, channel->name);
2867 if (ret) {
2868 goto end;
2869 }
2870
2871 lttng_channel_destroy(channel);
2872 }
2873 channel = nullptr;
2874
2875 /* get the trackers node */
2876 for (node = xmlFirstElementChild(domain_node); node; node = xmlNextElementSibling(node)) {
2877 if (!strcmp((const char *) node->name, config_element_process_attr_trackers) ||
2878 !strcmp((const char *) node->name, config_element_trackers_legacy)) {
2879 if (trackers_node) {
2880 ERR("Only one instance of `%s` or `%s` is allowed in a session configuration",
2881 config_element_process_attr_trackers,
2882 config_element_trackers_legacy);
2883 ret = -1;
2884 goto end;
2885 }
2886 trackers_node = node;
2887 break;
2888 }
2889 }
2890
2891 if (!trackers_node) {
2892 goto end;
2893 }
2894
2895 for (node = xmlFirstElementChild(trackers_node); node; node = xmlNextElementSibling(node)) {
2896 if (!strcmp((const char *) node->name, config_element_process_attr_tracker_pid)) {
2897 pid_tracker_node = node;
2898 ret = process_id_tracker_node(
2899 pid_tracker_node, handle, LTTNG_PROCESS_ATTR_PROCESS_ID);
2900 if (ret) {
2901 goto end;
2902 }
2903 }
2904 if (!strcmp((const char *) node->name, config_element_process_attr_tracker_vpid)) {
2905 vpid_tracker_node = node;
2906 ret = process_id_tracker_node(
2907 vpid_tracker_node, handle, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
2908 if (ret) {
2909 goto end;
2910 }
2911 }
2912 if (!strcmp((const char *) node->name, config_element_process_attr_tracker_uid)) {
2913 uid_tracker_node = node;
2914 ret = process_id_tracker_node(
2915 uid_tracker_node, handle, LTTNG_PROCESS_ATTR_USER_ID);
2916 if (ret) {
2917 goto end;
2918 }
2919 }
2920 if (!strcmp((const char *) node->name, config_element_process_attr_tracker_vuid)) {
2921 vuid_tracker_node = node;
2922 ret = process_id_tracker_node(
2923 vuid_tracker_node, handle, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
2924 if (ret) {
2925 goto end;
2926 }
2927 }
2928 if (!strcmp((const char *) node->name, config_element_process_attr_tracker_gid)) {
2929 gid_tracker_node = node;
2930 ret = process_id_tracker_node(
2931 gid_tracker_node, handle, LTTNG_PROCESS_ATTR_GROUP_ID);
2932 if (ret) {
2933 goto end;
2934 }
2935 }
2936 if (!strcmp((const char *) node->name, config_element_process_attr_tracker_vgid)) {
2937 vgid_tracker_node = node;
2938 ret = process_id_tracker_node(
2939 vgid_tracker_node, handle, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
2940 if (ret) {
2941 goto end;
2942 }
2943 }
2944 if (!strcmp((const char *) node->name, config_element_pid_tracker_legacy)) {
2945 ret = process_legacy_pid_tracker_node(node, handle);
2946 if (ret) {
2947 goto end;
2948 }
2949 }
2950 }
2951
2952 end:
2953 lttng_channel_destroy(channel);
2954 lttng_destroy_handle(handle);
2955 return ret;
2956 }
2957
2958 static int add_periodic_rotation(const char *name, uint64_t time_us)
2959 {
2960 int ret;
2961 enum lttng_rotation_status status;
2962 struct lttng_rotation_schedule *periodic = lttng_rotation_schedule_periodic_create();
2963
2964 if (!periodic) {
2965 ret = -LTTNG_ERR_NOMEM;
2966 goto error;
2967 }
2968
2969 status = lttng_rotation_schedule_periodic_set_period(periodic, time_us);
2970 if (status != LTTNG_ROTATION_STATUS_OK) {
2971 ret = -LTTNG_ERR_INVALID;
2972 goto error;
2973 }
2974
2975 status = lttng_session_add_rotation_schedule(name, periodic);
2976 switch (status) {
2977 case LTTNG_ROTATION_STATUS_OK:
2978 ret = 0;
2979 break;
2980 case LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET:
2981 case LTTNG_ROTATION_STATUS_INVALID:
2982 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
2983 break;
2984 default:
2985 ret = -LTTNG_ERR_UNK;
2986 break;
2987 }
2988 error:
2989 lttng_rotation_schedule_destroy(periodic);
2990 return ret;
2991 }
2992
2993 static int add_size_rotation(const char *name, uint64_t size_bytes)
2994 {
2995 int ret;
2996 enum lttng_rotation_status status;
2997 struct lttng_rotation_schedule *size = lttng_rotation_schedule_size_threshold_create();
2998
2999 if (!size) {
3000 ret = -LTTNG_ERR_NOMEM;
3001 goto error;
3002 }
3003
3004 status = lttng_rotation_schedule_size_threshold_set_threshold(size, size_bytes);
3005 if (status != LTTNG_ROTATION_STATUS_OK) {
3006 ret = -LTTNG_ERR_INVALID;
3007 goto error;
3008 }
3009
3010 status = lttng_session_add_rotation_schedule(name, size);
3011 switch (status) {
3012 case LTTNG_ROTATION_STATUS_OK:
3013 ret = 0;
3014 break;
3015 case LTTNG_ROTATION_STATUS_SCHEDULE_ALREADY_SET:
3016 case LTTNG_ROTATION_STATUS_INVALID:
3017 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3018 break;
3019 default:
3020 ret = -LTTNG_ERR_UNK;
3021 break;
3022 }
3023 error:
3024 lttng_rotation_schedule_destroy(size);
3025 return ret;
3026 }
3027
3028 static int process_session_rotation_schedules_node(xmlNodePtr schedules_node,
3029 uint64_t *rotation_timer_interval,
3030 uint64_t *rotation_size)
3031 {
3032 int ret = 0;
3033 xmlNodePtr child;
3034
3035 for (child = xmlFirstElementChild(schedules_node); child;
3036 child = xmlNextElementSibling(child)) {
3037 if (!strcmp((const char *) child->name,
3038 config_element_rotation_schedule_periodic)) {
3039 xmlChar *content;
3040 xmlNodePtr time_us_node;
3041
3042 /* periodic rotation schedule */
3043 time_us_node = xmlFirstElementChild(child);
3044 if (!time_us_node ||
3045 strcmp((const char *) time_us_node->name,
3046 config_element_rotation_schedule_periodic_time_us) != 0) {
3047 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3048 goto end;
3049 }
3050
3051 /* time_us child */
3052 content = xmlNodeGetContent(time_us_node);
3053 if (!content) {
3054 ret = -LTTNG_ERR_NOMEM;
3055 goto end;
3056 }
3057 ret = parse_uint(content, rotation_timer_interval);
3058 free(content);
3059 if (ret) {
3060 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3061 goto end;
3062 }
3063 } else if (!strcmp((const char *) child->name,
3064 config_element_rotation_schedule_size_threshold)) {
3065 xmlChar *content;
3066 xmlNodePtr bytes_node;
3067
3068 /* size_threshold rotation schedule */
3069 bytes_node = xmlFirstElementChild(child);
3070 if (!bytes_node ||
3071 strcmp((const char *) bytes_node->name,
3072 config_element_rotation_schedule_size_threshold_bytes) != 0) {
3073 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3074 goto end;
3075 }
3076
3077 /* bytes child */
3078 content = xmlNodeGetContent(bytes_node);
3079 if (!content) {
3080 ret = -LTTNG_ERR_NOMEM;
3081 goto end;
3082 }
3083 ret = parse_uint(content, rotation_size);
3084 free(content);
3085 if (ret) {
3086 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3087 goto end;
3088 }
3089 }
3090 }
3091
3092 end:
3093 return ret;
3094 }
3095
3096 static int process_session_node(xmlNodePtr session_node,
3097 const char *session_name,
3098 int overwrite,
3099 const struct config_load_session_override_attr *overrides)
3100 {
3101 int ret = -1, started = -1, snapshot_mode = -1;
3102 uint64_t live_timer_interval = UINT64_MAX, rotation_timer_interval = 0, rotation_size = 0;
3103 xmlChar *name = nullptr;
3104 xmlChar *shm_path = nullptr;
3105 xmlNodePtr domains_node = nullptr;
3106 xmlNodePtr output_node = nullptr;
3107 xmlNodePtr node;
3108 xmlNodePtr attributes_child;
3109 struct lttng_domain *kernel_domain = nullptr;
3110 struct lttng_domain *ust_domain = nullptr;
3111 struct lttng_domain *jul_domain = nullptr;
3112 struct lttng_domain *log4j_domain = nullptr;
3113 struct lttng_domain *log4j2_domain = nullptr;
3114 struct lttng_domain *python_domain = nullptr;
3115
3116 for (node = xmlFirstElementChild(session_node); node; node = xmlNextElementSibling(node)) {
3117 if (!name && !strcmp((const char *) node->name, config_element_name)) {
3118 /* name */
3119 xmlChar *node_content = xmlNodeGetContent(node);
3120 if (!node_content) {
3121 ret = -LTTNG_ERR_NOMEM;
3122 goto error;
3123 }
3124
3125 name = node_content;
3126 } else if (!domains_node &&
3127 !strcmp((const char *) node->name, config_element_domains)) {
3128 /* domains */
3129 domains_node = node;
3130 } else if (started == -1 &&
3131 !strcmp((const char *) node->name, config_element_started)) {
3132 /* started */
3133 xmlChar *node_content = xmlNodeGetContent(node);
3134 if (!node_content) {
3135 ret = -LTTNG_ERR_NOMEM;
3136 goto error;
3137 }
3138
3139 ret = parse_bool(node_content, &started);
3140 free(node_content);
3141 if (ret) {
3142 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3143 goto error;
3144 }
3145 } else if (!output_node &&
3146 !strcmp((const char *) node->name, config_element_output)) {
3147 /* output */
3148 output_node = node;
3149 } else if (!shm_path &&
3150 !strcmp((const char *) node->name, config_element_shared_memory_path)) {
3151 /* shared memory path */
3152 xmlChar *node_content = xmlNodeGetContent(node);
3153 if (!node_content) {
3154 ret = -LTTNG_ERR_NOMEM;
3155 goto error;
3156 }
3157
3158 shm_path = node_content;
3159 } else {
3160 /*
3161 * attributes, snapshot_mode, live_timer_interval, rotation_size,
3162 * rotation_timer_interval.
3163 */
3164 for (attributes_child = xmlFirstElementChild(node); attributes_child;
3165 attributes_child = xmlNextElementSibling(attributes_child)) {
3166 if (!strcmp((const char *) attributes_child->name,
3167 config_element_snapshot_mode)) {
3168 /* snapshot_mode */
3169 xmlChar *snapshot_mode_content =
3170 xmlNodeGetContent(attributes_child);
3171 if (!snapshot_mode_content) {
3172 ret = -LTTNG_ERR_NOMEM;
3173 goto error;
3174 }
3175
3176 ret = parse_bool(snapshot_mode_content, &snapshot_mode);
3177 free(snapshot_mode_content);
3178 if (ret) {
3179 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3180 goto error;
3181 }
3182 } else if (!strcmp((const char *) attributes_child->name,
3183 config_element_live_timer_interval)) {
3184 /* live_timer_interval */
3185 xmlChar *timer_interval_content =
3186 xmlNodeGetContent(attributes_child);
3187 if (!timer_interval_content) {
3188 ret = -LTTNG_ERR_NOMEM;
3189 goto error;
3190 }
3191
3192 ret = parse_uint(timer_interval_content,
3193 &live_timer_interval);
3194 free(timer_interval_content);
3195 if (ret) {
3196 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3197 goto error;
3198 }
3199 } else if (!strcmp((const char *) attributes_child->name,
3200 config_element_rotation_schedules)) {
3201 ret = process_session_rotation_schedules_node(
3202 attributes_child,
3203 &rotation_timer_interval,
3204 &rotation_size);
3205 if (ret) {
3206 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3207 goto error;
3208 }
3209 }
3210 }
3211 }
3212 }
3213
3214 if (!name) {
3215 /* Mandatory attribute, as defined in the session XSD */
3216 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3217 goto error;
3218 }
3219
3220 if (session_name && strcmp((char *) name, session_name) != 0) {
3221 /* This is not the session we are looking for */
3222 ret = -LTTNG_ERR_NO_SESSION;
3223 goto error;
3224 }
3225
3226 /* Init domains to create the session handles */
3227 for (node = xmlFirstElementChild(domains_node); node; node = xmlNextElementSibling(node)) {
3228 lttng_domain *domain = zmalloc<lttng_domain>();
3229
3230 if (!domain) {
3231 ret = -LTTNG_ERR_NOMEM;
3232 goto error;
3233 }
3234
3235 ret = init_domain(node, domain);
3236 if (ret) {
3237 goto domain_init_error;
3238 }
3239
3240 switch (domain->type) {
3241 case LTTNG_DOMAIN_KERNEL:
3242 if (kernel_domain) {
3243 /* Same domain seen twice, invalid! */
3244 goto domain_init_error;
3245 }
3246 kernel_domain = domain;
3247 break;
3248 case LTTNG_DOMAIN_UST:
3249 if (ust_domain) {
3250 /* Same domain seen twice, invalid! */
3251 goto domain_init_error;
3252 }
3253 ust_domain = domain;
3254 break;
3255 case LTTNG_DOMAIN_JUL:
3256 if (jul_domain) {
3257 /* Same domain seen twice, invalid! */
3258 goto domain_init_error;
3259 }
3260 jul_domain = domain;
3261 break;
3262 case LTTNG_DOMAIN_LOG4J:
3263 if (log4j_domain) {
3264 /* Same domain seen twice, invalid! */
3265 goto domain_init_error;
3266 }
3267 log4j_domain = domain;
3268 break;
3269 case LTTNG_DOMAIN_LOG4J2:
3270 if (log4j2_domain) {
3271 /* Same domain seen twice, invalid! */
3272 goto domain_init_error;
3273 }
3274 log4j2_domain = domain;
3275 break;
3276 case LTTNG_DOMAIN_PYTHON:
3277 if (python_domain) {
3278 /* Same domain seen twice, invalid! */
3279 goto domain_init_error;
3280 }
3281 python_domain = domain;
3282 break;
3283 default:
3284 WARN("Invalid domain type");
3285 goto domain_init_error;
3286 }
3287 continue;
3288 domain_init_error:
3289 free(domain);
3290 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3291 goto error;
3292 }
3293
3294 /* Apply overrides */
3295 if (overrides) {
3296 if (overrides->session_name) {
3297 xmlChar *name_override = xmlStrdup(BAD_CAST(overrides->session_name));
3298 if (!name_override) {
3299 ret = -LTTNG_ERR_NOMEM;
3300 goto error;
3301 }
3302
3303 /* Overrides the session name to the provided name */
3304 xmlFree(name);
3305 name = name_override;
3306 }
3307 }
3308
3309 if (overwrite) {
3310 /* Destroy session if it exists */
3311 ret = lttng_destroy_session((const char *) name);
3312 if (ret && ret != -LTTNG_ERR_SESS_NOT_FOUND) {
3313 ERR("Failed to destroy existing session.");
3314 goto error;
3315 }
3316 }
3317
3318 /* Create session type depending on output type */
3319 if (snapshot_mode && snapshot_mode != -1) {
3320 ret = create_snapshot_session((const char *) name, output_node, overrides);
3321 } else if (live_timer_interval && live_timer_interval != UINT64_MAX) {
3322 ret = create_session(
3323 (const char *) name, output_node, live_timer_interval, overrides);
3324 } else {
3325 /* regular session */
3326 ret = create_session((const char *) name, output_node, UINT64_MAX, overrides);
3327 }
3328 if (ret) {
3329 goto error;
3330 }
3331
3332 if (shm_path) {
3333 ret = lttng_set_session_shm_path((const char *) name, (const char *) shm_path);
3334 if (ret) {
3335 goto error;
3336 }
3337 }
3338
3339 for (node = xmlFirstElementChild(domains_node); node; node = xmlNextElementSibling(node)) {
3340 ret = process_domain_node(node, (const char *) name);
3341 if (ret) {
3342 goto end;
3343 }
3344 }
3345
3346 if (rotation_timer_interval) {
3347 ret = add_periodic_rotation((const char *) name, rotation_timer_interval);
3348 if (ret < 0) {
3349 goto error;
3350 }
3351 }
3352 if (rotation_size) {
3353 ret = add_size_rotation((const char *) name, rotation_size);
3354 if (ret < 0) {
3355 goto error;
3356 }
3357 }
3358
3359 if (started) {
3360 ret = lttng_start_tracing((const char *) name);
3361 if (ret) {
3362 goto end;
3363 }
3364 }
3365
3366 end:
3367 if (ret < 0) {
3368 ERR("Failed to load session %s: %s", (const char *) name, lttng_strerror(ret));
3369 lttng_destroy_session((const char *) name);
3370 }
3371
3372 error:
3373 free(kernel_domain);
3374 free(ust_domain);
3375 free(jul_domain);
3376 free(log4j_domain);
3377 free(log4j2_domain);
3378 free(python_domain);
3379 xmlFree(name);
3380 xmlFree(shm_path);
3381 return ret;
3382 }
3383
3384 /*
3385 * Return 1 if the given path is readable by the current UID or 0 if not.
3386 * Return -1 if the path is EPERM.
3387 */
3388 static int validate_file_read_creds(const char *path)
3389 {
3390 int ret;
3391
3392 LTTNG_ASSERT(path);
3393
3394 /* Can we read the file. */
3395 ret = access(path, R_OK);
3396 if (!ret) {
3397 goto valid;
3398 }
3399 if (errno == EACCES) {
3400 return -1;
3401 } else {
3402 /* Invalid. */
3403 return 0;
3404 }
3405 valid:
3406 return 1;
3407 }
3408
3409 static int load_session_from_file(const char *path,
3410 const char *session_name,
3411 struct session_config_validation_ctx *validation_ctx,
3412 int overwrite,
3413 const struct config_load_session_override_attr *overrides)
3414 {
3415 int ret, session_found = !session_name;
3416 xmlDocPtr doc = nullptr;
3417 xmlNodePtr sessions_node;
3418 xmlNodePtr session_node;
3419
3420 LTTNG_ASSERT(path);
3421 LTTNG_ASSERT(validation_ctx);
3422
3423 ret = validate_file_read_creds(path);
3424 if (ret != 1) {
3425 if (ret == -1) {
3426 ret = -LTTNG_ERR_EPERM;
3427 } else {
3428 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3429 }
3430 goto end;
3431 }
3432
3433 doc = xmlParseFile(path);
3434 if (!doc) {
3435 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3436 goto end;
3437 }
3438
3439 ret = xmlSchemaValidateDoc(validation_ctx->schema_validation_ctx, doc);
3440 if (ret) {
3441 ERR("Session configuration file validation failed");
3442 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3443 goto end;
3444 }
3445
3446 sessions_node = xmlDocGetRootElement(doc);
3447 if (!sessions_node) {
3448 ret = -LTTNG_ERR_LOAD_INVALID_CONFIG;
3449 goto end;
3450 }
3451
3452 for (session_node = xmlFirstElementChild(sessions_node); session_node;
3453 session_node = xmlNextElementSibling(session_node)) {
3454 ret = process_session_node(session_node, session_name, overwrite, overrides);
3455 if (!session_name && ret) {
3456 /* Loading error occurred. */
3457 goto end;
3458 } else if (session_name) {
3459 if (ret == 0) {
3460 /* Target session found and loaded */
3461 session_found = 1;
3462 break;
3463 } else if (ret == -LTTNG_ERR_NO_SESSION) {
3464 /*
3465 * Ignore this error, we are looking for a
3466 * specific session.
3467 */
3468 ret = 0;
3469 } else {
3470 /* Loading error occurred. */
3471 goto end;
3472 }
3473 }
3474 }
3475 end:
3476 xmlFreeDoc(doc);
3477 if (!ret) {
3478 ret = session_found ? 0 : -LTTNG_ERR_LOAD_SESSION_NOENT;
3479 }
3480 return ret;
3481 }
3482
3483 static int load_session_from_path(const char *path,
3484 const char *session_name,
3485 struct session_config_validation_ctx *validation_ctx,
3486 int overwrite,
3487 const struct config_load_session_override_attr *overrides)
3488 {
3489 int ret, session_found = !session_name;
3490 DIR *directory = nullptr;
3491 struct lttng_dynamic_buffer file_path;
3492 size_t path_len;
3493
3494 LTTNG_ASSERT(path);
3495 LTTNG_ASSERT(validation_ctx);
3496 path_len = strlen(path);
3497 lttng_dynamic_buffer_init(&file_path);
3498 if (path_len >= LTTNG_PATH_MAX) {
3499 ERR("Session configuration load path \"%s\" length (%zu) exceeds the maximal length allowed (%d)",
3500 path,
3501 path_len,
3502 LTTNG_PATH_MAX);
3503 ret = -LTTNG_ERR_INVALID;
3504 goto end;
3505 }
3506
3507 directory = opendir(path);
3508 if (!directory) {
3509 switch (errno) {
3510 case ENOTDIR:
3511 /* Try the file loading. */
3512 break;
3513 case ENOENT:
3514 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3515 goto end;
3516 default:
3517 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3518 goto end;
3519 }
3520 }
3521 if (directory) {
3522 size_t file_path_root_len;
3523
3524 ret = lttng_dynamic_buffer_set_capacity(&file_path, LTTNG_PATH_MAX);
3525 if (ret) {
3526 ret = -LTTNG_ERR_NOMEM;
3527 goto end;
3528 }
3529
3530 ret = lttng_dynamic_buffer_append(&file_path, path, path_len);
3531 if (ret) {
3532 ret = -LTTNG_ERR_NOMEM;
3533 goto end;
3534 }
3535
3536 if (file_path.data[file_path.size - 1] != '/') {
3537 ret = lttng_dynamic_buffer_append(&file_path, "/", 1);
3538 if (ret) {
3539 ret = -LTTNG_ERR_NOMEM;
3540 goto end;
3541 }
3542 }
3543 file_path_root_len = file_path.size;
3544
3545 /* Search for *.lttng files */
3546 for (;;) {
3547 size_t file_name_len;
3548 struct dirent *result;
3549
3550 /*
3551 * When the end of the directory stream is reached, NULL
3552 * is returned and errno is kept unchanged. When an
3553 * error occurs, NULL is returned and errno is set
3554 * accordingly. To distinguish between the two, set
3555 * errno to zero before calling readdir().
3556 *
3557 * On success, readdir() returns a pointer to a dirent
3558 * structure. This structure may be statically
3559 * allocated, do not attempt to free(3) it.
3560 */
3561 errno = 0;
3562 result = readdir(directory);
3563
3564 /* Reached end of dir stream or error out. */
3565 if (!result) {
3566 if (errno) {
3567 PERROR("Failed to enumerate the contents of path \"%s\" while loading session, readdir returned",
3568 path);
3569 ret = -LTTNG_ERR_LOAD_IO_FAIL;
3570 goto end;
3571 }
3572 break;
3573 }
3574
3575 file_name_len = strlen(result->d_name);
3576
3577 if (file_name_len <= sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION)) {
3578 continue;
3579 }
3580
3581 if (file_path.size + file_name_len >= LTTNG_PATH_MAX) {
3582 WARN("Ignoring file \"%s\" since the path's length (%zu) would exceed the maximal permitted size (%d)",
3583 result->d_name,
3584 /* +1 to account for NULL terminator. */
3585 file_path.size + file_name_len + 1,
3586 LTTNG_PATH_MAX);
3587 continue;
3588 }
3589
3590 /* Does the file end with .lttng? */
3591 if (strcmp(DEFAULT_SESSION_CONFIG_FILE_EXTENSION,
3592 result->d_name + file_name_len -
3593 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION) + 1) !=
3594 0) {
3595 continue;
3596 }
3597
3598 ret = lttng_dynamic_buffer_append(
3599 &file_path, result->d_name, file_name_len + 1);
3600 if (ret) {
3601 ret = -LTTNG_ERR_NOMEM;
3602 goto end;
3603 }
3604
3605 ret = load_session_from_file(
3606 file_path.data, session_name, validation_ctx, overwrite, overrides);
3607 if (session_name && (!ret || ret != -LTTNG_ERR_LOAD_SESSION_NOENT)) {
3608 session_found = 1;
3609 break;
3610 }
3611 if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
3612 goto end;
3613 }
3614 /*
3615 * Reset the buffer's size to the location of the
3616 * path's trailing '/'.
3617 */
3618 ret = lttng_dynamic_buffer_set_size(&file_path, file_path_root_len);
3619 if (ret) {
3620 ret = -LTTNG_ERR_UNK;
3621 goto end;
3622 }
3623 }
3624 } else {
3625 ret = load_session_from_file(
3626 path, session_name, validation_ctx, overwrite, overrides);
3627 if (ret) {
3628 goto end;
3629 }
3630 session_found = 1;
3631 }
3632
3633 ret = 0;
3634 end:
3635 if (directory) {
3636 if (closedir(directory)) {
3637 PERROR("closedir");
3638 }
3639 }
3640 if (!ret && !session_found) {
3641 ret = -LTTNG_ERR_LOAD_SESSION_NOENT;
3642 }
3643 lttng_dynamic_buffer_reset(&file_path);
3644 return ret;
3645 }
3646
3647 /*
3648 * Validate that the given path's credentials and the current process have the
3649 * same UID. If so, return 1 else return 0 if it does NOT match.
3650 */
3651 static int validate_path_creds(const char *path)
3652 {
3653 int ret, uid = getuid();
3654 struct stat buf;
3655
3656 LTTNG_ASSERT(path);
3657
3658 if (uid == 0) {
3659 goto valid;
3660 }
3661
3662 ret = stat(path, &buf);
3663 if (ret < 0) {
3664 if (errno != ENOENT) {
3665 PERROR("stat");
3666 }
3667 goto valid;
3668 }
3669
3670 if (buf.st_uid != uid) {
3671 goto invalid;
3672 }
3673
3674 valid:
3675 return 1;
3676 invalid:
3677 return 0;
3678 }
3679
3680 int config_load_session(const char *path,
3681 const char *session_name,
3682 int overwrite,
3683 unsigned int autoload,
3684 const struct config_load_session_override_attr *overrides)
3685 {
3686 int ret;
3687 bool session_loaded = false;
3688 const char *path_ptr = nullptr;
3689 struct session_config_validation_ctx validation_ctx = {};
3690 const char *home_path = nullptr;
3691 char path_buf[PATH_MAX];
3692
3693 ret = init_session_config_validation_ctx(&validation_ctx);
3694 if (ret) {
3695 goto end;
3696 }
3697
3698 if (!path) {
3699 /* Try home path */
3700 home_path = utils_get_home_dir();
3701 if (home_path) {
3702 /*
3703 * Try user session configuration path. Ignore error here so we can
3704 * continue loading the system wide sessions.
3705 */
3706 if (autoload) {
3707 ret = snprintf(path_buf,
3708 sizeof(path_buf),
3709 DEFAULT_SESSION_HOME_CONFIGPATH
3710 "/" DEFAULT_SESSION_CONFIG_AUTOLOAD,
3711 home_path);
3712 if (ret < 0) {
3713 PERROR("snprintf session autoload home config path");
3714 ret = -LTTNG_ERR_INVALID;
3715 goto end;
3716 }
3717
3718 /*
3719 * Credentials are only validated for the autoload in order to
3720 * avoid any user session daemon to try to load kernel sessions
3721 * automatically and failing all the times.
3722 */
3723 ret = validate_path_creds(path_buf);
3724 if (ret) {
3725 path_ptr = path_buf;
3726 }
3727 } else {
3728 ret = snprintf(path_buf,
3729 sizeof(path_buf),
3730 DEFAULT_SESSION_HOME_CONFIGPATH,
3731 home_path);
3732 if (ret < 0) {
3733 PERROR("snprintf session home config path");
3734 ret = -LTTNG_ERR_INVALID;
3735 goto end;
3736 }
3737 path_ptr = path_buf;
3738 }
3739 if (path_ptr) {
3740 ret = load_session_from_path(path_ptr,
3741 session_name,
3742 &validation_ctx,
3743 overwrite,
3744 overrides);
3745 if (ret && ret != -LTTNG_ERR_LOAD_SESSION_NOENT) {
3746 goto end;
3747 }
3748 /*
3749 * Continue even if the session was found since we have to try
3750 * the system wide sessions.
3751 */
3752 session_loaded = true;
3753 }
3754 }
3755
3756 /* Reset path pointer for the system wide dir. */
3757 path_ptr = nullptr;
3758
3759 /* Try system wide configuration directory. */
3760 const auto sys_path =
3761 lttng::make_unique_wrapper<char, lttng::memory::free>(utils_get_rundir(0));
3762 if (!sys_path) {
3763 ret = -LTTNG_ERR_INVALID;
3764 goto end;
3765 }
3766
3767 if (autoload) {
3768 ret = snprintf(path_buf,
3769 sizeof(path_buf),
3770 DEFAULT_SESSION_CONFIGPATH
3771 "/" DEFAULT_SESSION_CONFIG_AUTOLOAD,
3772 sys_path.get());
3773 if (ret < 0) {
3774 PERROR("snprintf session auto sys config path");
3775 ret = -LTTNG_ERR_INVALID;
3776 goto end;
3777 }
3778 ret = validate_path_creds(sys_path.get());
3779 if (ret) {
3780 path_ptr = sys_path.get();
3781 }
3782 } else {
3783 ret = snprintf(path_buf,
3784 sizeof(path_buf),
3785 DEFAULT_SESSION_CONFIGPATH,
3786 sys_path.get());
3787 if (ret < 0) {
3788 PERROR("snprintf session sys config path");
3789 ret = -LTTNG_ERR_INVALID;
3790 goto end;
3791 }
3792 }
3793
3794 if (path_ptr) {
3795 ret = load_session_from_path(
3796 path_ptr, session_name, &validation_ctx, overwrite, overrides);
3797 if (!ret) {
3798 session_loaded = true;
3799 }
3800 } else {
3801 ret = 0;
3802 }
3803 } else {
3804 ret = access(path, F_OK);
3805 if (ret < 0) {
3806 PERROR("access");
3807 switch (errno) {
3808 case ENOENT:
3809 ret = -LTTNG_ERR_INVALID;
3810 WARN("Session configuration path does not exist.");
3811 break;
3812 case EACCES:
3813 ret = -LTTNG_ERR_EPERM;
3814 break;
3815 default:
3816 ret = -LTTNG_ERR_UNK;
3817 break;
3818 }
3819 goto end;
3820 }
3821
3822 ret = load_session_from_path(
3823 path, session_name, &validation_ctx, overwrite, overrides);
3824 }
3825 end:
3826 fini_session_config_validation_ctx(&validation_ctx);
3827 if (ret == -LTTNG_ERR_LOAD_SESSION_NOENT && !session_name && !path) {
3828 /*
3829 * Don't report an error if no sessions are found when called
3830 * without a session_name or a search path.
3831 */
3832 ret = 0;
3833 }
3834
3835 if (session_loaded && ret == -LTTNG_ERR_LOAD_SESSION_NOENT) {
3836 /* A matching session was found in one of the search paths. */
3837 ret = 0;
3838 }
3839 return ret;
3840 }
3841
3842 static void __attribute__((destructor)) session_config_exit()
3843 {
3844 xmlCleanupParser();
3845 }
This page took 0.135229 seconds and 5 git commands to generate.