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