Fix: possible unlink on uninitialized buffer path
[lttng-tools.git] / src / bin / lttng-sessiond / save.c
1 /*
2 * Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _GNU_SOURCE
19 #include <assert.h>
20 #include <inttypes.h>
21 #include <string.h>
22 #include <urcu/uatomic.h>
23 #include <unistd.h>
24
25 #include <common/defaults.h>
26 #include <common/error.h>
27 #include <common/config/config.h>
28 #include <common/config/config-session-internal.h>
29 #include <common/utils.h>
30 #include <common/runas.h>
31 #include <lttng/save-internal.h>
32
33 #include "save.h"
34 #include "session.h"
35 #include "trace-ust.h"
36
37 static
38 int save_kernel_channel_attributes(struct config_writer *writer,
39 struct lttng_channel_attr *attr)
40 {
41 int ret;
42
43 ret = config_writer_write_element_string(writer,
44 config_element_overwrite_mode,
45 attr->overwrite ? config_overwrite_mode_overwrite :
46 config_overwrite_mode_discard);
47 if (ret) {
48 goto end;
49 }
50
51 ret = config_writer_write_element_unsigned_int(writer,
52 config_element_subbuf_size, attr->subbuf_size);
53 if (ret) {
54 goto end;
55 }
56
57 ret = config_writer_write_element_unsigned_int(writer,
58 config_element_num_subbuf,
59 attr->num_subbuf);
60 if (ret) {
61 goto end;
62 }
63
64 ret = config_writer_write_element_unsigned_int(writer,
65 config_element_switch_timer_interval,
66 attr->switch_timer_interval);
67 if (ret) {
68 goto end;
69 }
70
71 ret = config_writer_write_element_unsigned_int(writer,
72 config_element_read_timer_interval,
73 attr->read_timer_interval);
74 if (ret) {
75 goto end;
76 }
77
78 ret = config_writer_write_element_string(writer,
79 config_element_output_type,
80 attr->output == LTTNG_EVENT_SPLICE ?
81 config_output_type_splice : config_output_type_mmap);
82 if (ret) {
83 goto end;
84 }
85
86 ret = config_writer_write_element_unsigned_int(writer,
87 config_element_tracefile_size, attr->tracefile_size);
88 if (ret) {
89 goto end;
90 }
91
92 ret = config_writer_write_element_unsigned_int(writer,
93 config_element_tracefile_count,
94 attr->tracefile_count);
95 if (ret) {
96 goto end;
97 }
98
99 ret = config_writer_write_element_unsigned_int(writer,
100 config_element_live_timer_interval,
101 attr->live_timer_interval);
102 if (ret) {
103 goto end;
104 }
105 end:
106 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
107 }
108
109 static
110 int save_ust_channel_attributes(struct config_writer *writer,
111 struct lttng_ust_channel_attr *attr)
112 {
113 int ret;
114
115 ret = config_writer_write_element_string(writer,
116 config_element_overwrite_mode,
117 attr->overwrite ? config_overwrite_mode_overwrite :
118 config_overwrite_mode_discard);
119 if (ret) {
120 goto end;
121 }
122
123 ret = config_writer_write_element_unsigned_int(writer,
124 config_element_subbuf_size, attr->subbuf_size);
125 if (ret) {
126 goto end;
127 }
128
129 ret = config_writer_write_element_unsigned_int(writer,
130 config_element_num_subbuf,
131 attr->num_subbuf);
132 if (ret) {
133 goto end;
134 }
135
136 ret = config_writer_write_element_unsigned_int(writer,
137 config_element_switch_timer_interval,
138 attr->switch_timer_interval);
139 if (ret) {
140 goto end;
141 }
142
143 ret = config_writer_write_element_unsigned_int(writer,
144 config_element_read_timer_interval,
145 attr->read_timer_interval);
146 if (ret) {
147 goto end;
148 }
149
150 ret = config_writer_write_element_string(writer,
151 config_element_output_type,
152 attr->output == LTTNG_UST_MMAP ?
153 config_output_type_mmap : config_output_type_splice);
154 if (ret) {
155 goto end;
156 }
157 end:
158 return ret ? LTTNG_ERR_SAVE_IO_FAIL : 0;
159 }
160
161 static
162 const char *get_kernel_instrumentation_string(
163 enum lttng_kernel_instrumentation instrumentation)
164 {
165 const char *instrumentation_string;
166
167 switch (instrumentation) {
168 case LTTNG_KERNEL_ALL:
169 instrumentation_string = config_event_type_all;
170 break;
171 case LTTNG_KERNEL_TRACEPOINT:
172 instrumentation_string = config_event_type_tracepoint;
173 break;
174 case LTTNG_KERNEL_KPROBE:
175 instrumentation_string = config_event_type_kprobe;
176 break;
177 case LTTNG_KERNEL_FUNCTION:
178 instrumentation_string = config_event_type_function;
179 break;
180 case LTTNG_KERNEL_KRETPROBE:
181 instrumentation_string = config_event_type_kretprobe;
182 break;
183 case LTTNG_KERNEL_NOOP:
184 instrumentation_string = config_event_type_noop;
185 break;
186 case LTTNG_KERNEL_SYSCALL:
187 instrumentation_string = config_event_type_syscall;
188 break;
189 default:
190 instrumentation_string = NULL;
191 }
192
193 return instrumentation_string;
194 }
195
196 static
197 const char *get_kernel_context_type_string(
198 enum lttng_kernel_context_type context_type)
199 {
200 const char *context_type_string;
201
202 switch (context_type) {
203 case LTTNG_KERNEL_CONTEXT_PID:
204 context_type_string = config_event_context_pid;
205 break;
206 case LTTNG_KERNEL_CONTEXT_PROCNAME:
207 context_type_string = config_event_context_procname;
208 break;
209 case LTTNG_KERNEL_CONTEXT_PRIO:
210 context_type_string = config_event_context_prio;
211 break;
212 case LTTNG_KERNEL_CONTEXT_NICE:
213 context_type_string = config_event_context_nice;
214 break;
215 case LTTNG_KERNEL_CONTEXT_VPID:
216 context_type_string = config_event_context_vpid;
217 break;
218 case LTTNG_KERNEL_CONTEXT_TID:
219 context_type_string = config_event_context_tid;
220 break;
221 case LTTNG_KERNEL_CONTEXT_VTID:
222 context_type_string = config_event_context_vtid;
223 break;
224 case LTTNG_KERNEL_CONTEXT_PPID:
225 context_type_string = config_event_context_ppid;
226 break;
227 case LTTNG_KERNEL_CONTEXT_VPPID:
228 context_type_string = config_event_context_vppid;
229 break;
230 case LTTNG_KERNEL_CONTEXT_HOSTNAME:
231 context_type_string = config_event_context_hostname;
232 break;
233 default:
234 context_type_string = NULL;
235 }
236
237 return context_type_string;
238 }
239
240 static
241 const char *get_ust_context_type_string(
242 enum lttng_ust_context_type context_type)
243 {
244 const char *context_type_string;
245
246 switch (context_type) {
247 case LTTNG_UST_CONTEXT_PROCNAME:
248 context_type_string = config_event_context_procname;
249 break;
250 case LTTNG_UST_CONTEXT_VPID:
251 context_type_string = config_event_context_vpid;
252 break;
253 case LTTNG_UST_CONTEXT_VTID:
254 context_type_string = config_event_context_vtid;
255 break;
256 case LTTNG_UST_CONTEXT_IP:
257 context_type_string = config_event_context_ip;
258 break;
259 case LTTNG_UST_CONTEXT_PTHREAD_ID:
260 context_type_string = config_event_context_pthread_id;
261 break;
262 default:
263 context_type_string = NULL;
264 }
265
266 return context_type_string;
267 }
268
269 static
270 const char *get_buffer_type_string(
271 enum lttng_buffer_type buffer_type)
272 {
273 const char *buffer_type_string;
274
275 switch (buffer_type) {
276 case LTTNG_BUFFER_PER_PID:
277 buffer_type_string = config_buffer_type_per_pid;
278 break;
279 case LTTNG_BUFFER_PER_UID:
280 buffer_type_string = config_buffer_type_per_uid;
281 break;
282 case LTTNG_BUFFER_GLOBAL:
283 buffer_type_string = config_buffer_type_global;
284 break;
285 default:
286 buffer_type_string = NULL;
287 }
288
289 return buffer_type_string;
290 }
291
292 static
293 const char *get_loglevel_type_string(
294 enum lttng_ust_loglevel_type loglevel_type)
295 {
296 const char *loglevel_type_string;
297
298 switch (loglevel_type) {
299 case LTTNG_UST_LOGLEVEL_ALL:
300 loglevel_type_string = config_loglevel_type_all;
301 break;
302 case LTTNG_UST_LOGLEVEL_RANGE:
303 loglevel_type_string = config_loglevel_type_range;
304 break;
305 case LTTNG_UST_LOGLEVEL_SINGLE:
306 loglevel_type_string = config_loglevel_type_single;
307 break;
308 default:
309 loglevel_type_string = NULL;
310 }
311
312 return loglevel_type_string;
313 }
314
315 static
316 int save_kernel_event(struct config_writer *writer,
317 struct ltt_kernel_event *event)
318 {
319 int ret;
320 const char *instrumentation_type;
321
322 ret = config_writer_open_element(writer, config_element_event);
323 if (ret) {
324 ret = LTTNG_ERR_SAVE_IO_FAIL;
325 goto end;
326 }
327
328 if (event->event->name[0]) {
329 ret = config_writer_write_element_string(writer,
330 config_element_name, event->event->name);
331 if (ret) {
332 ret = LTTNG_ERR_SAVE_IO_FAIL;
333 goto end;
334 }
335 }
336
337 ret = config_writer_write_element_bool(writer, config_element_enabled,
338 event->enabled);
339 if (ret) {
340 ret = LTTNG_ERR_SAVE_IO_FAIL;
341 goto end;
342 }
343
344 instrumentation_type = get_kernel_instrumentation_string(
345 event->event->instrumentation);
346 if (!instrumentation_type) {
347 ret = LTTNG_ERR_INVALID;
348 goto end;
349 }
350
351 ret = config_writer_write_element_string(writer, config_element_type,
352 instrumentation_type);
353 if (ret) {
354 ret = LTTNG_ERR_SAVE_IO_FAIL;
355 goto end;
356 }
357
358 if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
359 event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
360 event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
361
362 ret = config_writer_open_element(writer,
363 config_element_attributes);
364 if (ret) {
365 ret = LTTNG_ERR_SAVE_IO_FAIL;
366 goto end;
367 }
368
369 switch (event->event->instrumentation) {
370 case LTTNG_KERNEL_FUNCTION:
371 ret = config_writer_open_element(writer,
372 config_element_function_attributes);
373 if (ret) {
374 ret = LTTNG_ERR_SAVE_IO_FAIL;
375 goto end;
376 }
377
378 ret = config_writer_write_element_string(writer,
379 config_element_name,
380 event->event->u.ftrace.symbol_name);
381 if (ret) {
382 ret = LTTNG_ERR_SAVE_IO_FAIL;
383 goto end;
384 }
385
386 /* /function attributes */
387 ret = config_writer_close_element(writer);
388 if (ret) {
389 ret = LTTNG_ERR_SAVE_IO_FAIL;
390 goto end;
391 }
392 break;
393 case LTTNG_KERNEL_KPROBE:
394 case LTTNG_KERNEL_KRETPROBE:
395 {
396 const char *symbol_name;
397 uint64_t addr;
398 uint64_t offset;
399
400 if (event->event->instrumentation ==
401 LTTNG_KERNEL_KPROBE) {
402 /*
403 * Comments in lttng-kernel.h mention that
404 * either addr or symbol_name are set, not both.
405 */
406 addr = event->event->u.kprobe.addr;
407 offset = event->event->u.kprobe.offset;
408 symbol_name = addr ? NULL :
409 event->event->u.kprobe.symbol_name;
410 } else {
411 symbol_name =
412 event->event->u.kretprobe.symbol_name;
413 addr = event->event->u.kretprobe.addr;
414 offset = event->event->u.kretprobe.offset;
415 }
416
417 ret = config_writer_open_element(writer,
418 config_element_probe_attributes);
419 if (ret) {
420 ret = LTTNG_ERR_SAVE_IO_FAIL;
421 goto end;
422 }
423
424 if (symbol_name) {
425 ret = config_writer_write_element_string(writer,
426 config_element_symbol_name,
427 symbol_name);
428 if (ret) {
429 ret = LTTNG_ERR_SAVE_IO_FAIL;
430 goto end;
431 }
432 }
433
434 if (addr) {
435 ret = config_writer_write_element_unsigned_int(
436 writer, config_element_address, addr);
437 if (ret) {
438 ret = LTTNG_ERR_SAVE_IO_FAIL;
439 goto end;
440 }
441 }
442
443 if (offset) {
444 ret = config_writer_write_element_unsigned_int(
445 writer, config_element_offset, offset);
446 if (ret) {
447 ret = LTTNG_ERR_SAVE_IO_FAIL;
448 goto end;
449 }
450 }
451
452 ret = config_writer_close_element(writer);
453 if (ret) {
454 ret = LTTNG_ERR_SAVE_IO_FAIL;
455 goto end;
456 }
457 break;
458 }
459 default:
460 ERR("Unsupported kernel instrumentation type.");
461 ret = LTTNG_ERR_INVALID;
462 goto end;
463 }
464
465 /* /attributes */
466 ret = config_writer_close_element(writer);
467 if (ret) {
468 ret = LTTNG_ERR_SAVE_IO_FAIL;
469 goto end;
470 }
471 }
472
473 /* /event */
474 ret = config_writer_close_element(writer);
475 if (ret) {
476 ret = LTTNG_ERR_SAVE_IO_FAIL;
477 goto end;
478 }
479 end:
480 return ret;
481 }
482
483 static
484 int save_kernel_events(struct config_writer *writer,
485 struct ltt_kernel_event_list *event_list)
486 {
487 int ret;
488 struct ltt_kernel_event *event;
489
490 ret = config_writer_open_element(writer, config_element_events);
491 if (ret) {
492 ret = LTTNG_ERR_SAVE_IO_FAIL;
493 goto end;
494 }
495
496 cds_list_for_each_entry(event, &event_list->head, list) {
497 ret = save_kernel_event(writer, event);
498 if (ret) {
499 goto end;
500 }
501 }
502
503 /* /events */
504 ret = config_writer_close_element(writer);
505 if (ret) {
506 ret = LTTNG_ERR_SAVE_IO_FAIL;
507 goto end;
508 }
509 end:
510 return ret;
511 }
512
513 static
514 int save_ust_event(struct config_writer *writer,
515 struct ltt_ust_event *event)
516 {
517 int ret;
518 const char *loglevel_type_string;
519
520 ret = config_writer_open_element(writer, config_element_event);
521 if (ret) {
522 ret = LTTNG_ERR_SAVE_IO_FAIL;
523 goto end;
524 }
525
526 if (event->attr.name[0]) {
527 ret = config_writer_write_element_string(writer,
528 config_element_name, event->attr.name);
529 if (ret) {
530 ret = LTTNG_ERR_SAVE_IO_FAIL;
531 goto end;
532 }
533 }
534
535 ret = config_writer_write_element_bool(writer, config_element_enabled,
536 event->enabled);
537 if (ret) {
538 ret = LTTNG_ERR_SAVE_IO_FAIL;
539 goto end;
540 }
541
542 if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
543 ERR("Unsupported UST instrumentation type.");
544 ret = LTTNG_ERR_INVALID;
545 goto end;
546 }
547 ret = config_writer_write_element_string(writer, config_element_type,
548 config_event_type_tracepoint);
549 if (ret) {
550 ret = LTTNG_ERR_SAVE_IO_FAIL;
551 goto end;
552 }
553
554 loglevel_type_string = get_loglevel_type_string(
555 event->attr.loglevel_type);
556 if (!loglevel_type_string) {
557 ERR("Unsupported UST loglevel type.");
558 ret = LTTNG_ERR_INVALID;
559 goto end;
560 }
561
562 ret = config_writer_write_element_string(writer,
563 config_element_loglevel_type, loglevel_type_string);
564 if (ret) {
565 ret = LTTNG_ERR_SAVE_IO_FAIL;
566 goto end;
567 }
568
569 ret = config_writer_write_element_signed_int(writer,
570 config_element_loglevel, event->attr.loglevel);
571 if (ret) {
572 ret = LTTNG_ERR_SAVE_IO_FAIL;
573 goto end;
574 }
575
576 if (event->filter_expression) {
577 ret = config_writer_write_element_string(writer,
578 config_element_filter, event->filter_expression);
579 if (ret) {
580 ret = LTTNG_ERR_SAVE_IO_FAIL;
581 goto end;
582 }
583 }
584
585 if (event->exclusion && event->exclusion->count) {
586 uint32_t i;
587
588 ret = config_writer_open_element(writer,
589 config_element_exclusions);
590 if (ret) {
591 ret = LTTNG_ERR_SAVE_IO_FAIL;
592 goto end;
593 }
594
595 for (i = 0; i < event->exclusion->count; i++) {
596 ret = config_writer_write_element_string(writer,
597 config_element_exclusion,
598 &event->exclusion->names[0][i]);
599 if (ret) {
600 ret = LTTNG_ERR_SAVE_IO_FAIL;
601 goto end;
602 }
603 }
604
605 /* /exclusions */
606 ret = config_writer_close_element(writer);
607 if (ret) {
608 ret = LTTNG_ERR_SAVE_IO_FAIL;
609 goto end;
610 }
611 }
612
613 /* /event */
614 ret = config_writer_close_element(writer);
615 if (ret) {
616 ret = LTTNG_ERR_SAVE_IO_FAIL;
617 goto end;
618 }
619 end:
620 return ret;
621 }
622
623 static
624 int save_ust_events(struct config_writer *writer,
625 struct lttng_ht *events)
626 {
627 int ret;
628 struct ltt_ust_event *event;
629 struct lttng_ht_node_str *node;
630 struct lttng_ht_iter iter;
631
632 ret = config_writer_open_element(writer, config_element_events);
633 if (ret) {
634 ret = LTTNG_ERR_SAVE_IO_FAIL;
635 goto end;
636 }
637
638 rcu_read_lock();
639 cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) {
640 event = caa_container_of(node, struct ltt_ust_event, node);
641
642 ret = save_ust_event(writer, event);
643 if (ret) {
644 rcu_read_unlock();
645 goto end;
646 }
647 }
648 rcu_read_unlock();
649
650 /* /events */
651 ret = config_writer_close_element(writer);
652 if (ret) {
653 ret = LTTNG_ERR_SAVE_IO_FAIL;
654 goto end;
655 }
656 end:
657 return ret;
658 }
659
660 static
661 int save_kernel_context(struct config_writer *writer,
662 struct lttng_kernel_context *ctx)
663 {
664 int ret = 0;
665
666 if (!ctx) {
667 goto end;
668 }
669
670 ret = config_writer_open_element(writer, config_element_contexts);
671 if (ret) {
672 ret = LTTNG_ERR_SAVE_IO_FAIL;
673 goto end;
674 }
675
676 ret = config_writer_open_element(writer, config_element_context);
677 if (ret) {
678 ret = LTTNG_ERR_SAVE_IO_FAIL;
679 goto end;
680 }
681
682 if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) {
683 ret = config_writer_open_element(writer, config_element_perf);
684 if (ret) {
685 ret = LTTNG_ERR_SAVE_IO_FAIL;
686 goto end;
687 }
688
689 ret = config_writer_write_element_unsigned_int(writer,
690 config_element_type, ctx->u.perf_counter.type);
691 if (ret) {
692 ret = LTTNG_ERR_SAVE_IO_FAIL;
693 goto end;
694 }
695
696 ret = config_writer_write_element_unsigned_int(writer,
697 config_element_config, ctx->u.perf_counter.config);
698 if (ret) {
699 ret = LTTNG_ERR_SAVE_IO_FAIL;
700 goto end;
701 }
702
703 ret = config_writer_write_element_string(writer,
704 config_element_name, ctx->u.perf_counter.name);
705 if (ret) {
706 ret = LTTNG_ERR_SAVE_IO_FAIL;
707 goto end;
708 }
709
710 /* /perf */
711 ret = config_writer_close_element(writer);
712 if (ret) {
713 ret = LTTNG_ERR_SAVE_IO_FAIL;
714 goto end;
715 }
716 } else {
717 const char *context_type_string =
718 get_kernel_context_type_string(ctx->ctx);
719
720 if (!context_type_string) {
721 ERR("Unsupported kernel context type.");
722 ret = LTTNG_ERR_INVALID;
723 goto end;
724 }
725
726 ret = config_writer_write_element_string(writer,
727 config_element_type, context_type_string);
728 if (ret) {
729 ret = LTTNG_ERR_SAVE_IO_FAIL;
730 goto end;
731 }
732 }
733
734 /* /context */
735 ret = config_writer_close_element(writer);
736 if (ret) {
737 ret = LTTNG_ERR_SAVE_IO_FAIL;
738 goto end;
739 }
740
741 /* /contexts */
742 ret = config_writer_close_element(writer);
743 if (ret) {
744 ret = LTTNG_ERR_SAVE_IO_FAIL;
745 goto end;
746 }
747 end:
748 return ret;
749 }
750
751 static
752 int save_ust_context(struct config_writer *writer,
753 struct cds_list_head *ctx_list)
754 {
755 int ret;
756 struct ltt_ust_context *ctx;
757
758 assert(writer);
759 assert(ctx_list);
760
761 ret = config_writer_open_element(writer, config_element_contexts);
762 if (ret) {
763 ret = LTTNG_ERR_SAVE_IO_FAIL;
764 goto end;
765 }
766
767 cds_list_for_each_entry(ctx, ctx_list, list) {
768 const char *context_type_string;
769
770 context_type_string = get_ust_context_type_string(ctx->ctx.ctx);
771 if (!context_type_string) {
772 ERR("Unsupported UST context type.")
773 ret = LTTNG_ERR_INVALID;
774 goto end;
775 }
776
777 ret = config_writer_open_element(writer,
778 config_element_context);
779 if (ret) {
780 ret = LTTNG_ERR_SAVE_IO_FAIL;
781 goto end;
782 }
783
784 ret = config_writer_write_element_string(writer,
785 config_element_type, context_type_string);
786 if (ret) {
787 ret = LTTNG_ERR_SAVE_IO_FAIL;
788 goto end;
789 }
790
791 /* /context */
792 ret = config_writer_close_element(writer);
793 if (ret) {
794 ret = LTTNG_ERR_SAVE_IO_FAIL;
795 goto end;
796 }
797 }
798
799 /* /contexts */
800 ret = config_writer_close_element(writer);
801 if (ret) {
802 ret = LTTNG_ERR_SAVE_IO_FAIL;
803 goto end;
804 }
805 end:
806 return ret;
807 }
808
809 static
810 int save_kernel_channel(struct config_writer *writer,
811 struct ltt_kernel_channel *kchan)
812 {
813 int ret;
814
815 assert(writer);
816 assert(kchan);
817
818 ret = config_writer_open_element(writer, config_element_channel);
819 if (ret) {
820 ret = LTTNG_ERR_SAVE_IO_FAIL;
821 goto end;
822 }
823
824 ret = config_writer_write_element_string(writer, config_element_name,
825 kchan->channel->name);
826 if (ret) {
827 ret = LTTNG_ERR_SAVE_IO_FAIL;
828 goto end;
829 }
830
831 ret = config_writer_write_element_bool(writer, config_element_enabled,
832 kchan->channel->enabled);
833 if (ret) {
834 ret = LTTNG_ERR_SAVE_IO_FAIL;
835 goto end;
836 }
837
838 ret = save_kernel_channel_attributes(writer, &kchan->channel->attr);
839 if (ret) {
840 goto end;
841 }
842
843 ret = save_kernel_events(writer, &kchan->events_list);
844 if (ret) {
845 goto end;
846 }
847
848 ret = save_kernel_context(writer, kchan->ctx);
849 if (ret) {
850 goto end;
851 }
852
853 /* /channel */
854 ret = config_writer_close_element(writer);
855 if (ret) {
856 ret = LTTNG_ERR_SAVE_IO_FAIL;
857 goto end;
858 }
859 end:
860 return ret;
861 }
862
863 static
864 int save_ust_channel(struct config_writer *writer,
865 struct ltt_ust_channel *ust_chan,
866 struct ltt_ust_session *session)
867 {
868 int ret;
869
870 assert(writer);
871 assert(ust_chan);
872 assert(session);
873
874 ret = config_writer_open_element(writer, config_element_channel);
875 if (ret) {
876 ret = LTTNG_ERR_SAVE_IO_FAIL;
877 goto end;
878 }
879
880 ret = config_writer_write_element_string(writer, config_element_name,
881 ust_chan->name);
882 if (ret) {
883 ret = LTTNG_ERR_SAVE_IO_FAIL;
884 goto end;
885 }
886
887 ret = config_writer_write_element_bool(writer, config_element_enabled,
888 ust_chan->enabled);
889 if (ret) {
890 ret = LTTNG_ERR_SAVE_IO_FAIL;
891 goto end;
892 }
893
894 ret = save_ust_channel_attributes(writer, &ust_chan->attr);
895 if (ret) {
896 goto end;
897 }
898
899 ret = config_writer_write_element_unsigned_int(writer,
900 config_element_tracefile_size, ust_chan->tracefile_size);
901 if (ret) {
902 ret = LTTNG_ERR_SAVE_IO_FAIL;
903 goto end;
904 }
905
906 ret = config_writer_write_element_unsigned_int(writer,
907 config_element_tracefile_count, ust_chan->tracefile_count);
908 if (ret) {
909 ret = LTTNG_ERR_SAVE_IO_FAIL;
910 goto end;
911 }
912
913 ret = config_writer_write_element_unsigned_int(writer,
914 config_element_live_timer_interval,
915 session->live_timer_interval);
916 if (ret) {
917 ret = LTTNG_ERR_SAVE_IO_FAIL;
918 goto end;
919 }
920
921 ret = save_ust_events(writer, ust_chan->events);
922 if (ret) {
923 ret = LTTNG_ERR_SAVE_IO_FAIL;
924 goto end;
925 }
926
927 ret = save_ust_context(writer, &ust_chan->ctx_list);
928 if (ret) {
929 goto end;
930 }
931
932 /* /channel */
933 ret = config_writer_close_element(writer);
934 if (ret) {
935 ret = LTTNG_ERR_SAVE_IO_FAIL;
936 goto end;
937 }
938 end:
939 return ret;
940 }
941
942 static
943 int save_kernel_session(struct config_writer *writer,
944 struct ltt_session *session)
945 {
946 int ret;
947 struct ltt_kernel_channel *kchan;
948
949 assert(writer);
950 assert(session);
951
952 ret = config_writer_write_element_string(writer, config_element_type,
953 config_domain_type_kernel);
954 if (ret) {
955 ret = LTTNG_ERR_SAVE_IO_FAIL;
956 goto end;
957 }
958
959 ret = config_writer_write_element_string(writer,
960 config_element_buffer_type, config_buffer_type_global);
961 if (ret) {
962 ret = LTTNG_ERR_SAVE_IO_FAIL;
963 goto end;
964 }
965
966 ret = config_writer_open_element(writer,
967 config_element_channels);
968 if (ret) {
969 ret = LTTNG_ERR_SAVE_IO_FAIL;
970 goto end;
971 }
972
973 cds_list_for_each_entry(kchan, &session->kernel_session->channel_list.head,
974 list) {
975 ret = save_kernel_channel(writer, kchan);
976 if (ret) {
977 goto end;
978 }
979 }
980
981 /* /channels */
982 ret = config_writer_close_element(writer);
983 if (ret) {
984 ret = LTTNG_ERR_SAVE_IO_FAIL;
985 goto end;
986 }
987 end:
988 return ret;
989 }
990
991 static
992 int save_ust_session(struct config_writer *writer,
993 struct ltt_session *session, int save_jul)
994 {
995 int ret;
996 struct ltt_ust_channel *ust_chan;
997 const char *buffer_type_string;
998 struct lttng_ht_node_str *node;
999 struct lttng_ht_iter iter;
1000
1001 assert(writer);
1002 assert(session);
1003
1004 ret = config_writer_write_element_string(writer, config_element_type,
1005 save_jul ? config_domain_type_jul : config_domain_type_ust);
1006 if (ret) {
1007 ret = LTTNG_ERR_SAVE_IO_FAIL;
1008 goto end;
1009 }
1010
1011 buffer_type_string = get_buffer_type_string(
1012 session->ust_session->buffer_type);
1013 if (!buffer_type_string) {
1014 ERR("Unsupported buffer type.");
1015 ret = LTTNG_ERR_INVALID;
1016 goto end;
1017 }
1018
1019 ret = config_writer_write_element_string(writer,
1020 config_element_buffer_type, buffer_type_string);
1021 if (ret) {
1022 ret = LTTNG_ERR_SAVE_IO_FAIL;
1023 goto end;
1024 }
1025
1026 ret = config_writer_open_element(writer, config_element_channels);
1027 if (ret) {
1028 ret = LTTNG_ERR_SAVE_IO_FAIL;
1029 goto end;
1030 }
1031
1032 rcu_read_lock();
1033 cds_lfht_for_each_entry(session->ust_session->domain_global.channels->ht,
1034 &iter.iter, node, node) {
1035 int jul_channel;
1036
1037 ust_chan = caa_container_of(node, struct ltt_ust_channel, node);
1038 jul_channel = !strcmp(DEFAULT_JUL_CHANNEL_NAME, ust_chan->name);
1039 if (!(save_jul ^ jul_channel)) {
1040 ret = save_ust_channel(writer, ust_chan, session->ust_session);
1041 if (ret) {
1042 rcu_read_unlock();
1043 goto end;
1044 }
1045 }
1046 }
1047 rcu_read_unlock();
1048
1049 /* /channels */
1050 ret = config_writer_close_element(writer);
1051 if (ret) {
1052 ret = LTTNG_ERR_SAVE_IO_FAIL;
1053 goto end;
1054 }
1055 end:
1056 return ret;
1057 }
1058
1059 static
1060 int save_domains(struct config_writer *writer, struct ltt_session *session)
1061 {
1062 int ret = 0;
1063
1064 assert(writer);
1065 assert(session);
1066
1067 if (!session->kernel_session && !session->ust_session) {
1068 goto end;
1069 }
1070
1071 ret = config_writer_open_element(writer, config_element_domains);
1072 if (ret) {
1073 ret = LTTNG_ERR_SAVE_IO_FAIL;
1074 goto end;
1075 }
1076
1077
1078 if (session->kernel_session) {
1079 ret = config_writer_open_element(writer,
1080 config_element_domain);
1081 if (ret) {
1082 ret = LTTNG_ERR_SAVE_IO_FAIL;
1083 goto end;
1084 }
1085
1086 ret = save_kernel_session(writer, session);
1087 if (ret) {
1088 goto end;
1089 }
1090
1091 /* /domain */
1092 ret = config_writer_close_element(writer);
1093 if (ret) {
1094 ret = LTTNG_ERR_SAVE_IO_FAIL;
1095 goto end;
1096 }
1097 }
1098
1099 if (session->ust_session) {
1100 ret = config_writer_open_element(writer,
1101 config_element_domain);
1102 if (ret) {
1103 ret = LTTNG_ERR_SAVE_IO_FAIL;
1104 goto end;
1105 }
1106
1107 ret = save_ust_session(writer, session, 0);
1108 if (ret) {
1109 goto end;
1110 }
1111
1112 /* /domain */
1113 ret = config_writer_close_element(writer);
1114 if (ret) {
1115 ret = LTTNG_ERR_SAVE_IO_FAIL;
1116 goto end;
1117 }
1118 }
1119
1120 if (session->ust_session &&
1121 session->ust_session->domain_jul.being_used) {
1122 ret = config_writer_open_element(writer,
1123 config_element_domain);
1124 if (ret) {
1125 ret = LTTNG_ERR_SAVE_IO_FAIL;
1126 goto end;
1127 }
1128
1129 ret = save_ust_session(writer, session, 1);
1130 if (ret) {
1131 goto end;
1132 }
1133
1134 /* /domain */
1135 ret = config_writer_close_element(writer);
1136 if (ret) {
1137 ret = LTTNG_ERR_SAVE_IO_FAIL;
1138 goto end;
1139 }
1140 }
1141
1142 /* /domains */
1143 ret = config_writer_close_element(writer);
1144 if (ret) {
1145 ret = LTTNG_ERR_SAVE_IO_FAIL;
1146 goto end;
1147 }
1148 end:
1149 return ret;
1150 }
1151
1152 static
1153 int save_consumer_output(struct config_writer *writer,
1154 struct consumer_output *output)
1155 {
1156 int ret;
1157
1158 assert(writer);
1159 assert(output);
1160
1161 ret = config_writer_open_element(writer, config_element_consumer_output);
1162 if (ret) {
1163 ret = LTTNG_ERR_SAVE_IO_FAIL;
1164 goto end;
1165 }
1166
1167 ret = config_writer_write_element_bool(writer, config_element_enabled,
1168 output->enabled);
1169 if (ret) {
1170 ret = LTTNG_ERR_SAVE_IO_FAIL;
1171 goto end;
1172 }
1173
1174 ret = config_writer_open_element(writer, config_element_destination);
1175 if (ret) {
1176 ret = LTTNG_ERR_SAVE_IO_FAIL;
1177 goto end;
1178 }
1179
1180 switch (output->type) {
1181 case CONSUMER_DST_LOCAL:
1182 ret = config_writer_write_element_string(writer,
1183 config_element_path, output->dst.trace_path);
1184 if (ret) {
1185 ret = LTTNG_ERR_SAVE_IO_FAIL;
1186 goto end;
1187 }
1188 break;
1189 case CONSUMER_DST_NET:
1190 {
1191 char *uri;
1192
1193 uri = zmalloc(PATH_MAX);
1194 if (!uri) {
1195 ret = LTTNG_ERR_NOMEM;
1196 goto end;
1197 }
1198
1199 ret = config_writer_open_element(writer, config_element_net_output);
1200 if (ret) {
1201 ret = LTTNG_ERR_SAVE_IO_FAIL;
1202 goto end_net_output;
1203 }
1204
1205 if (output->dst.net.control_isset &&
1206 output->dst.net.data_isset) {
1207 ret = uri_to_str_url(&output->dst.net.control, uri, PATH_MAX);
1208 if (ret < 0) {
1209 ret = LTTNG_ERR_INVALID;
1210 goto end_net_output;
1211 }
1212
1213 ret = config_writer_write_element_string(writer,
1214 config_element_control_uri, uri);
1215 if (ret) {
1216 ret = LTTNG_ERR_SAVE_IO_FAIL;
1217 goto end_net_output;
1218 }
1219
1220 ret = uri_to_str_url(&output->dst.net.data, uri, PATH_MAX);
1221 if (ret < 0) {
1222 ret = LTTNG_ERR_INVALID;
1223 goto end_net_output;
1224 }
1225
1226 ret = config_writer_write_element_string(writer,
1227 config_element_data_uri, uri);
1228 if (ret) {
1229 ret = LTTNG_ERR_SAVE_IO_FAIL;
1230 goto end_net_output;
1231 }
1232
1233 end_net_output:
1234 free(uri);
1235 if (ret) {
1236 goto end;
1237 }
1238 } else {
1239 ret = !output->dst.net.control_isset ?
1240 LTTNG_ERR_URL_CTRL_MISS :
1241 LTTNG_ERR_URL_DATA_MISS;
1242 free(uri);
1243 goto end;
1244 }
1245
1246 ret = config_writer_close_element(writer);
1247 if (ret) {
1248 ret = LTTNG_ERR_SAVE_IO_FAIL;
1249 goto end;
1250 }
1251 break;
1252 }
1253 default:
1254 ERR("Unsupported consumer output type.");
1255 ret = LTTNG_ERR_INVALID;
1256 goto end;
1257 }
1258
1259 /* /destination */
1260 ret = config_writer_close_element(writer);
1261 if (ret) {
1262 ret = LTTNG_ERR_SAVE_IO_FAIL;
1263 goto end;
1264 }
1265
1266 /* /consumer_output */
1267 ret = config_writer_close_element(writer);
1268 if (ret) {
1269 ret = LTTNG_ERR_SAVE_IO_FAIL;
1270 goto end;
1271 }
1272 end:
1273 return ret;
1274 }
1275
1276 static
1277 int save_snapshot_outputs(struct config_writer *writer,
1278 struct snapshot *snapshot)
1279 {
1280 int ret;
1281 struct lttng_ht_iter iter;
1282 struct snapshot_output *output;
1283
1284 assert(writer);
1285 assert(snapshot);
1286
1287 ret = config_writer_open_element(writer, config_element_snapshot_outputs);
1288 if (ret) {
1289 ret = LTTNG_ERR_SAVE_IO_FAIL;
1290 goto end;
1291 }
1292
1293 rcu_read_lock();
1294 cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
1295 node.node) {
1296 ret = config_writer_open_element(writer,
1297 config_element_output);
1298 if (ret) {
1299 ret = LTTNG_ERR_SAVE_IO_FAIL;
1300 goto end_unlock;
1301 }
1302
1303 ret = config_writer_write_element_string(writer,
1304 config_element_name, output->name);
1305 if (ret) {
1306 ret = LTTNG_ERR_SAVE_IO_FAIL;
1307 goto end_unlock;
1308 }
1309
1310 ret = config_writer_write_element_unsigned_int(writer,
1311 config_element_max_size, output->max_size);
1312 if (ret) {
1313 ret = LTTNG_ERR_SAVE_IO_FAIL;
1314 goto end_unlock;
1315 }
1316
1317 ret = save_consumer_output(writer, output->consumer);
1318 if (ret) {
1319 goto end_unlock;
1320 }
1321
1322 /* /output */
1323 ret = config_writer_close_element(writer);
1324 if (ret) {
1325 ret = LTTNG_ERR_SAVE_IO_FAIL;
1326 goto end_unlock;
1327 }
1328 }
1329 rcu_read_unlock();
1330
1331 /* /snapshot_outputs */
1332 ret = config_writer_close_element(writer);
1333 if (ret) {
1334 ret = LTTNG_ERR_SAVE_IO_FAIL;
1335 goto end;
1336 }
1337
1338 end:
1339 return ret;
1340 end_unlock:
1341 rcu_read_unlock();
1342 return ret;
1343 }
1344
1345 static
1346 int save_session_output(struct config_writer *writer,
1347 struct ltt_session *session)
1348 {
1349 int ret;
1350
1351 assert(writer);
1352 assert(session);
1353
1354 if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
1355 (!session->snapshot_mode && !session->consumer)) {
1356 /* Session is in no output mode */
1357 ret = 0;
1358 goto end;
1359 }
1360
1361 ret = config_writer_open_element(writer, config_element_output);
1362 if (ret) {
1363 ret = LTTNG_ERR_SAVE_IO_FAIL;
1364 goto end;
1365 }
1366
1367 if (session->snapshot_mode) {
1368 ret = save_snapshot_outputs(writer, &session->snapshot);
1369 if (ret) {
1370 goto end;
1371 }
1372 } else {
1373 if (session->consumer) {
1374 ret = save_consumer_output(writer, session->consumer);
1375 if (ret) {
1376 goto end;
1377 }
1378 }
1379 }
1380
1381 /* /output */
1382 ret = config_writer_close_element(writer);
1383 if (ret) {
1384 ret = LTTNG_ERR_SAVE_IO_FAIL;
1385 goto end;
1386 }
1387 end:
1388 return ret;
1389 }
1390
1391 /*
1392 * Save the given session.
1393 *
1394 * Return 0 on success else a LTTNG_ERR* code.
1395 */
1396 static
1397 int save_session(struct ltt_session *session,
1398 struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
1399 {
1400 int ret, fd;
1401 unsigned int file_opened = 0; /* Indicate if the file has been opened */
1402 char config_file_path[PATH_MAX];
1403 size_t len;
1404 struct config_writer *writer = NULL;
1405 size_t session_name_len;
1406 const char *provided_path;
1407
1408 assert(session);
1409 assert(attr);
1410 assert(creds);
1411
1412 session_name_len = strlen(session->name);
1413
1414 if (!session_access_ok(session,
1415 LTTNG_SOCK_GET_UID_CRED(creds),
1416 LTTNG_SOCK_GET_GID_CRED(creds))) {
1417 ret = LTTNG_ERR_EPERM;
1418 goto end;
1419 }
1420
1421 provided_path = lttng_save_session_attr_get_output_url(attr);
1422 if (provided_path) {
1423 len = strlen(provided_path);
1424 if (len >= sizeof(config_file_path)) {
1425 ret = LTTNG_ERR_SET_URL;
1426 goto end;
1427 }
1428 strncpy(config_file_path, provided_path, len);
1429 } else {
1430 ssize_t ret_len;
1431 char *home_dir = utils_get_user_home_dir(
1432 LTTNG_SOCK_GET_UID_CRED(creds));
1433 if (!home_dir) {
1434 ret = LTTNG_ERR_SET_URL;
1435 goto end;
1436 }
1437
1438 ret_len = snprintf(config_file_path, sizeof(config_file_path),
1439 DEFAULT_SESSION_HOME_CONFIGPATH, home_dir);
1440 free(home_dir);
1441 if (ret_len < 0) {
1442 PERROR("snprintf save session");
1443 ret = LTTNG_ERR_SET_URL;
1444 goto end;
1445 }
1446 len = ret_len;
1447 }
1448
1449 /*
1450 * Check the path fits in the config file path dst including the '/'
1451 * followed by trailing .lttng extension and the NULL terminated string.
1452 */
1453 if ((len + session_name_len + 2 +
1454 sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION))
1455 > sizeof(config_file_path)) {
1456 ret = LTTNG_ERR_SET_URL;
1457 goto end;
1458 }
1459
1460 ret = run_as_mkdir_recursive(config_file_path, S_IRWXU | S_IRWXG,
1461 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1462 if (ret) {
1463 ret = LTTNG_ERR_SET_URL;
1464 goto end;
1465 }
1466
1467 /*
1468 * At this point, we know that everything fits in the buffer. Validation
1469 * was done just above.
1470 */
1471 config_file_path[len++] = '/';
1472 strncpy(config_file_path + len, session->name, session_name_len);
1473 len += session_name_len;
1474 strcpy(config_file_path + len, DEFAULT_SESSION_CONFIG_FILE_EXTENSION);
1475
1476 if (!access(config_file_path, F_OK) && !attr->overwrite) {
1477 /* A file with the same name already exists, skip */
1478 goto end;
1479 }
1480
1481 fd = run_as_open(config_file_path, O_CREAT | O_WRONLY | O_TRUNC,
1482 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
1483 LTTNG_SOCK_GET_UID_CRED(creds), LTTNG_SOCK_GET_GID_CRED(creds));
1484 if (fd < 0) {
1485 PERROR("Could not create configuration file");
1486 ret = LTTNG_ERR_SAVE_IO_FAIL;
1487 goto end;
1488 }
1489 file_opened = 1;
1490
1491 writer = config_writer_create(fd);
1492 if (!writer) {
1493 ret = LTTNG_ERR_NOMEM;
1494 goto end;
1495 }
1496
1497 ret = config_writer_open_element(writer, config_element_sessions);
1498 if (ret) {
1499 ret = LTTNG_ERR_SAVE_IO_FAIL;
1500 goto end;
1501 }
1502
1503 ret = config_writer_open_element(writer, config_element_session);
1504 if (ret) {
1505 ret = LTTNG_ERR_SAVE_IO_FAIL;
1506 goto end;
1507 }
1508
1509 ret = config_writer_write_element_string(writer, config_element_name,
1510 session->name);
1511 if (ret) {
1512 ret = LTTNG_ERR_SAVE_IO_FAIL;
1513 goto end;
1514 }
1515
1516 ret = save_domains(writer, session);
1517 if (ret) {
1518 goto end;
1519 }
1520
1521 ret = config_writer_write_element_bool(writer, config_element_started,
1522 session->enabled);
1523 if (ret) {
1524 ret = LTTNG_ERR_SAVE_IO_FAIL;
1525 goto end;
1526 }
1527
1528 if (session->snapshot_mode || session->live_timer) {
1529 ret = config_writer_open_element(writer, config_element_attributes);
1530 if (ret) {
1531 ret = LTTNG_ERR_SAVE_IO_FAIL;
1532 goto end;
1533 }
1534
1535 if (session->snapshot_mode) {
1536 ret = config_writer_write_element_bool(writer,
1537 config_element_snapshot_mode, 1);
1538 if (ret) {
1539 ret = LTTNG_ERR_SAVE_IO_FAIL;
1540 goto end;
1541 }
1542 } else {
1543 ret = config_writer_write_element_signed_int(writer,
1544 config_element_live_timer_interval, session->live_timer);
1545 if (ret) {
1546 ret = LTTNG_ERR_SAVE_IO_FAIL;
1547 goto end;
1548 }
1549 }
1550
1551 /* /attributes */
1552 ret = config_writer_close_element(writer);
1553 if (ret) {
1554 ret = LTTNG_ERR_SAVE_IO_FAIL;
1555 goto end;
1556 }
1557 }
1558
1559 ret = save_session_output(writer, session);
1560 if (ret) {
1561 goto end;
1562 }
1563
1564 /* /session */
1565 ret = config_writer_close_element(writer);
1566 if (ret) {
1567 ret = LTTNG_ERR_SAVE_IO_FAIL;
1568 goto end;
1569 }
1570
1571 /* /sessions */
1572 ret = config_writer_close_element(writer);
1573 if (ret) {
1574 ret = LTTNG_ERR_SAVE_IO_FAIL;
1575 goto end;
1576 }
1577 end:
1578 if (writer && config_writer_destroy(writer)) {
1579 /* Preserve the original error code */
1580 ret = ret ? ret : LTTNG_ERR_SAVE_IO_FAIL;
1581 }
1582 if (ret) {
1583 /* Delete file in case of error */
1584 if (file_opened && unlink(config_file_path)) {
1585 PERROR("Unlinking XML session configuration.");
1586 }
1587 }
1588
1589 return ret;
1590 }
1591
1592 int cmd_save_sessions(struct lttng_save_session_attr *attr,
1593 lttng_sock_cred *creds)
1594 {
1595 int ret;
1596 const char *session_name;
1597 struct ltt_session *session;
1598
1599 session_lock_list();
1600
1601 session_name = lttng_save_session_attr_get_session_name(attr);
1602 if (session_name) {
1603 session = session_find_by_name(session_name);
1604 if (!session) {
1605 ret = LTTNG_ERR_SESS_NOT_FOUND;
1606 goto end;
1607 }
1608
1609 session_lock(session);
1610 ret = save_session(session, attr, creds);
1611 session_unlock(session);
1612 if (ret) {
1613 goto end;
1614 }
1615 } else {
1616 struct ltt_session_list *list = session_get_list();
1617
1618 cds_list_for_each_entry(session, &list->head, list) {
1619 session_lock(session);
1620 ret = save_session(session, attr, creds);
1621 session_unlock(session);
1622
1623 /* Don't abort if we don't have the required permissions. */
1624 if (ret && ret != LTTNG_ERR_EPERM) {
1625 goto end;
1626 }
1627 }
1628 }
1629 ret = LTTNG_OK;
1630
1631 end:
1632 session_unlock_list();
1633 return ret;
1634 }
This page took 0.097538 seconds and 5 git commands to generate.