Fix: sessiond: rotation trigger leak
[lttng-tools.git] / src / common / channel.cpp
CommitLineData
999af9c1
JR
1/*
2 * Copyright (C) 2021 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
c9e313bc
SM
8#include <common/buffer-view.hpp>
9#include <common/dynamic-array.hpp>
10#include <common/dynamic-buffer.hpp>
11#include <common/error.hpp>
12#include <common/macros.hpp>
13#include <common/sessiond-comm/sessiond-comm.hpp>
14#include <lttng/channel-internal.hpp>
999af9c1
JR
15#include <lttng/channel.h>
16#include <lttng/constant.h>
c9e313bc 17#include <lttng/userspace-probe-internal.hpp>
999af9c1
JR
18
19static enum lttng_error_code flatten_lttng_channels(
20 struct lttng_dynamic_pointer_array *channels,
21 struct lttng_channel **flattened_channels);
22
23static enum lttng_error_code channel_list_create_from_buffer(
24 const struct lttng_buffer_view *buffer,
25 uint32_t count,
26 struct lttng_dynamic_pointer_array *channel_list);
27
28static void channel_list_destructor(void *ptr)
29{
30 struct lttng_channel *element = (struct lttng_channel *) ptr;
31
32 lttng_channel_destroy(element);
33}
34
35struct lttng_channel *lttng_channel_copy(const struct lttng_channel *src)
36{
37 struct lttng_channel_extended *extended = nullptr;
38 struct lttng_channel *channel = nullptr, *ret = nullptr;
39
64803277 40 channel = zmalloc<lttng_channel>();
999af9c1
JR
41 if (!channel) {
42 goto end;
43 }
44
45 *channel = *src;
46
47 if (src->attr.extended.ptr) {
64803277 48 extended = zmalloc<lttng_channel_extended>();
999af9c1
JR
49 if (!extended) {
50 goto end;
51 }
52 memcpy(extended, src->attr.extended.ptr, sizeof(*extended));
53 channel->attr.extended.ptr = extended;
54 extended = nullptr;
55 }
56
57 ret = channel;
58 channel = nullptr;
59end:
60 free(channel);
61 free(extended);
62 return ret;
63}
64
65/*
66 * The channel object is NOT populated.
67 */
68struct lttng_channel *lttng_channel_create_internal(void)
69{
70 struct lttng_channel *local_channel = nullptr, *ret = nullptr;
71 struct lttng_channel_extended *extended = nullptr;
72
64803277 73 local_channel = zmalloc<lttng_channel>();
999af9c1
JR
74 if (!local_channel) {
75 goto end;
76 }
77
78 /* Extended struct */
64803277 79 extended = zmalloc<lttng_channel_extended>();
999af9c1
JR
80 if (!extended) {
81 goto end;
82 }
83
84 local_channel->attr.extended.ptr = extended;
85 extended = nullptr;
86
87 ret = local_channel;
88 local_channel = nullptr;
89end:
90 free(extended);
91 free(local_channel);
92 return ret;
93}
94
95ssize_t lttng_channel_create_from_buffer(const struct lttng_buffer_view *view,
96 struct lttng_channel **channel)
97{
98 ssize_t ret, offset = 0;
99 struct lttng_channel *local_channel = nullptr;
100 const struct lttng_channel_comm *channel_comm;
101 struct lttng_channel_extended *extended = nullptr;
102
103 assert(channel);
104
105 if (!view || !channel) {
106 ret = -1;
107 goto end;
108 }
109
110 /*
111 * Create an 'internal' channel since `lttng_create_channel` requires a
112 * domain and we cannot infer the domain from the payload.
113 */
114 local_channel = lttng_channel_create_internal();
115 if (!local_channel) {
116 ret = -1;
117 goto end;
118 }
119
120 extended = (typeof(extended)) local_channel->attr.extended.ptr;
121
122 /* lttng_trigger_comm header */
123 {
124 const struct lttng_buffer_view comm_view =
125 lttng_buffer_view_from_view(view, offset,
126 sizeof(*channel_comm));
127
128 if (!lttng_buffer_view_is_valid(&comm_view)) {
129 ret = -1;
130 goto end;
131 }
132
133 channel_comm = (const struct lttng_channel_comm *)
134 comm_view.data;
135 offset += sizeof(*channel_comm);
136 }
137
138 {
139 const char *name;
140 const struct lttng_buffer_view name_view =
141 lttng_buffer_view_from_view(view, offset,
142 channel_comm->name_len);
143
999af9c1
JR
144 name = name_view.data;
145 if (!lttng_buffer_view_contains_string(
146 &name_view, name, channel_comm->name_len)) {
147 ret = -1;
148 goto end;
149 }
150
2d6df81a
JG
151 ret = lttng_strncpy(local_channel->name, name,
152 sizeof(local_channel->name));
153 if (ret) {
154 goto end;
155 }
156
999af9c1
JR
157 offset += channel_comm->name_len;
158 }
159
160 /* Populate the channel */
161 local_channel->enabled = channel_comm->enabled;
162
163 /* attr */
164 local_channel->attr.overwrite = channel_comm->overwrite;
165 local_channel->attr.subbuf_size = channel_comm->subbuf_size;
166 local_channel->attr.num_subbuf = channel_comm->num_subbuf;
167 local_channel->attr.switch_timer_interval =
168 channel_comm->switch_timer_interval;
169 local_channel->attr.read_timer_interval =
170 channel_comm->read_timer_interval;
171 local_channel->attr.output = (enum lttng_event_output) channel_comm->output;
172 local_channel->attr.tracefile_size = channel_comm->tracefile_size;
173 local_channel->attr.tracefile_count = channel_comm->tracefile_count;
174 local_channel->attr.live_timer_interval =
175 channel_comm->live_timer_interval;
176
177 extended->discarded_events = channel_comm->discarded_events;
178 extended->lost_packets = channel_comm->lost_packets;
179 extended->monitor_timer_interval = channel_comm->monitor_timer_interval;
180 extended->blocking_timeout = channel_comm->blocking_timeout;
181
182 *channel = local_channel;
183 local_channel = nullptr;
184
185 ret = offset;
186end:
187 lttng_channel_destroy(local_channel);
188 return ret;
189}
190
191int lttng_channel_serialize(
192 struct lttng_channel *channel, struct lttng_dynamic_buffer *buf)
193{
194 int ret;
195 size_t name_len;
1c9a0b0e 196 struct lttng_channel_comm channel_comm = {};
999af9c1
JR
197 struct lttng_channel_extended *extended;
198
199 assert(channel);
200 assert(buf);
201
202 extended = (struct lttng_channel_extended *) channel->attr.extended.ptr;
203
204 name_len = lttng_strnlen(channel->name, LTTNG_SYMBOL_NAME_LEN);
205 if (name_len == LTTNG_SYMBOL_NAME_LEN) {
206 /* channel name is not nullptr-terminated. */
207 ret = -1;
208 goto end;
209 }
210
211 /* Include string termination. */
212 name_len += 1;
213
214 /* Base field */
215 channel_comm.name_len = (uint32_t) name_len;
216 channel_comm.enabled = channel->enabled;
217
218 /* attr */
219 channel_comm.overwrite = channel->attr.overwrite;
220 channel_comm.subbuf_size = channel->attr.subbuf_size;
221 channel_comm.num_subbuf = channel->attr.num_subbuf;
222 channel_comm.switch_timer_interval =
223 channel->attr.switch_timer_interval;
224 channel_comm.read_timer_interval = channel->attr.read_timer_interval;
225 channel_comm.output = channel->attr.output;
226 channel_comm.tracefile_size = channel->attr.tracefile_size;
227 channel_comm.tracefile_count = channel->attr.tracefile_count;
228 channel_comm.live_timer_interval = channel->attr.live_timer_interval;
229
230 /* Extended struct */
231 channel_comm.discarded_events = extended->discarded_events;
232 channel_comm.lost_packets = extended->lost_packets;
233 channel_comm.monitor_timer_interval = extended->monitor_timer_interval;
234 channel_comm.blocking_timeout = extended->blocking_timeout;
235
236 /* Header */
237 ret = lttng_dynamic_buffer_append(
238 buf, &channel_comm, sizeof(channel_comm));
239 if (ret) {
240 goto end;
241 }
242
243 /* channel name */
244 ret = lttng_dynamic_buffer_append(buf, channel->name, name_len);
245 if (ret) {
246 goto end;
247 }
248end:
249 return ret;
250}
251
252void lttng_channel_set_default_extended_attr(struct lttng_domain *domain,
253 struct lttng_channel_extended *extended_attr)
254{
255 assert(domain);
256 assert(extended_attr);
257
258 memset(extended_attr, 0, sizeof(*extended_attr));
259
260 switch (domain->type) {
261 case LTTNG_DOMAIN_KERNEL:
262 extended_attr->monitor_timer_interval =
263 DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
264 extended_attr->blocking_timeout =
265 DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
266 break;
267 case LTTNG_DOMAIN_UST:
268 switch (domain->buf_type) {
269 case LTTNG_BUFFER_PER_UID:
270 extended_attr->monitor_timer_interval =
271 DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
272 extended_attr->blocking_timeout =
273 DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
274 break;
275 case LTTNG_BUFFER_PER_PID:
276 default:
277 if (extended_attr) {
278 extended_attr->monitor_timer_interval =
279 DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
280 extended_attr->blocking_timeout =
281 DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
282 }
283 break;
284 }
285 default:
286 /* Default behavior: leave set to 0. */
287 break;
288 }
289}
290
291static enum lttng_error_code channel_list_create_from_buffer(
292 const struct lttng_buffer_view *view,
293 unsigned int count,
294 struct lttng_dynamic_pointer_array *channel_list)
295{
296 enum lttng_error_code ret_code;
297 int ret, i;
298 int offset = 0;
299
300 assert(view);
301 assert(channel_list);
302
303 for (i = 0; i < count; i++) {
304 ssize_t channel_size;
305 struct lttng_channel *channel = nullptr;
306 const struct lttng_buffer_view channel_view =
307 lttng_buffer_view_from_view(view, offset, -1);
308
309 channel_size = lttng_channel_create_from_buffer(
310 &channel_view, &channel);
311 if (channel_size < 0) {
312 ret_code = LTTNG_ERR_INVALID;
313 goto end;
314 }
315
316 /* Lifetime and management of the object is now bound to the array. */
317 ret = lttng_dynamic_pointer_array_add_pointer(channel_list, channel);
318 if (ret) {
319 lttng_channel_destroy(channel);
320 ret_code = LTTNG_ERR_NOMEM;
321 goto end;
322 }
323 offset += channel_size;
324 }
325
326 if (view->size != offset) {
327 ret_code = LTTNG_ERR_INVALID;
328 goto end;
329 }
330
331 ret_code = LTTNG_OK;
332
333end:
334 return ret_code;
335}
336
337static enum lttng_error_code flatten_lttng_channels(struct lttng_dynamic_pointer_array *channels,
338 struct lttng_channel **flattened_channels)
339{
340 enum lttng_error_code ret_code;
341 int ret, i;
342 size_t storage_req = 0;
343 struct lttng_dynamic_buffer local_flattened_channels;
344 int nb_channels;
345
346 assert(channels);
347 assert(flattened_channels);
348
349 lttng_dynamic_buffer_init(&local_flattened_channels);
350 nb_channels = lttng_dynamic_pointer_array_get_count(channels);
351
352 storage_req += sizeof(struct lttng_channel) * nb_channels;
353 storage_req += sizeof(struct lttng_channel_extended) * nb_channels;
354
355 /*
356 * We must ensure that "local_flattened_channels" is never resized so as
357 * to preserve the validity of the flattened objects.
358 */
359 ret = lttng_dynamic_buffer_set_capacity(
360 &local_flattened_channels, storage_req);
361 if (ret) {
362 ret_code = LTTNG_ERR_NOMEM;
363 goto end;
364 }
365
366 /* Start by laying the struct lttng_channel */
367 for (i = 0; i < nb_channels; i++) {
368 const auto *element = (const struct lttng_channel *)
369 lttng_dynamic_pointer_array_get_pointer(
370 channels, i);
371
372 if (!element) {
373 ret_code = LTTNG_ERR_FATAL;
374 goto end;
375 }
376
377 ret = lttng_dynamic_buffer_append(&local_flattened_channels,
378 element, sizeof(struct lttng_channel));
379 if (ret) {
380 ret_code = LTTNG_ERR_NOMEM;
381 goto end;
382 }
383 }
384
385 /* Flatten the extended data */
386 for (i = 0; i < nb_channels; i++) {
387 const auto *element = (const struct lttng_channel *)
388 lttng_dynamic_pointer_array_get_pointer(
389 channels, i);
390 /*
391 * Sample the location of the flattened channel we are about
392 * to modify.
393 */
394 auto *channel = (struct lttng_channel *)
395 (local_flattened_channels.data + (sizeof(struct lttng_channel) * i));
396 /*
397 * Sample the location of the extended attributes we are about
398 * to add.
399 */
400 const auto *channel_extended = (struct lttng_channel_extended *)
401 (local_flattened_channels.data + local_flattened_channels.size);
402
403 if (!element) {
404 ret_code = LTTNG_ERR_FATAL;
405 goto end;
406 }
407
408 ret = lttng_dynamic_buffer_append(&local_flattened_channels,
409 element->attr.extended.ptr,
410 sizeof(struct lttng_channel_extended));
411 if (ret) {
412 ret_code = LTTNG_ERR_NOMEM;
413 goto end;
414 }
415
416 /*
417 * Update the flattened lttng_channel object with its flattened
418 * extended object location.
419 */
420 channel->attr.extended.ptr = (void *) channel_extended;
421 }
422
423 /* Don't reset local_flattened_channels buffer as we return its content. */
424 *flattened_channels = (struct lttng_channel *) local_flattened_channels.data;
425 lttng_dynamic_buffer_init(&local_flattened_channels);
426 ret_code = LTTNG_OK;
427end:
428 lttng_dynamic_buffer_reset(&local_flattened_channels);
429 return ret_code;
430}
431
432enum lttng_error_code lttng_channels_create_and_flatten_from_buffer(
433 const struct lttng_buffer_view *view,
434 uint32_t count,
435 struct lttng_channel **channels)
436{
437 enum lttng_error_code ret_code;
438 struct lttng_dynamic_pointer_array local_channels;
439
440 lttng_dynamic_pointer_array_init(&local_channels, channel_list_destructor);
441
442 /* Deserialize the channels */
443 {
444 const struct lttng_buffer_view channels_view =
445 lttng_buffer_view_from_view(view, 0, -1);
446
447 ret_code = channel_list_create_from_buffer(
448 &channels_view, count, &local_channels);
449 if (ret_code != LTTNG_OK) {
450 goto end;
451 }
452 }
453
454 ret_code = flatten_lttng_channels(&local_channels, channels);
455
456end:
457 lttng_dynamic_pointer_array_reset(&local_channels);
458 return ret_code;
459}
This page took 0.04421 seconds and 4 git commands to generate.