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