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