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