Fix: unchecked buffer size for communication header
[lttng-tools.git] / src / common / session-rotation.c
CommitLineData
c19092cd 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
c19092cd 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
c19092cd 5 *
c19092cd
JG
6 */
7
8#include <lttng/condition/condition-internal.h>
9#include <lttng/condition/session-rotation-internal.h>
10#include <lttng/location-internal.h>
11#include <common/macros.h>
12#include <common/error.h>
13#include <assert.h>
14#include <stdbool.h>
15
16static
17bool lttng_condition_session_rotation_validate(
18 const struct lttng_condition *condition);
19static
20int lttng_condition_session_rotation_serialize(
21 const struct lttng_condition *condition,
c0a66c84 22 struct lttng_payload *payload);
c19092cd
JG
23static
24bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
25 const struct lttng_condition *_b);
26static
27void lttng_condition_session_rotation_destroy(
28 struct lttng_condition *condition);
29
30static const
31struct lttng_condition rotation_condition_template = {
32 /* .type omitted; shall be set on creation. */
33 .validate = lttng_condition_session_rotation_validate,
34 .serialize = lttng_condition_session_rotation_serialize,
35 .equal = lttng_condition_session_rotation_is_equal,
36 .destroy = lttng_condition_session_rotation_destroy,
37};
38
39static
40int lttng_evaluation_session_rotation_serialize(
41 const struct lttng_evaluation *evaluation,
c0a66c84 42 struct lttng_payload *payload);
c19092cd
JG
43static
44void lttng_evaluation_session_rotation_destroy(
45 struct lttng_evaluation *evaluation);
46
47static const
48struct lttng_evaluation rotation_evaluation_template = {
49 /* .type omitted; shall be set on creation. */
50 .serialize = lttng_evaluation_session_rotation_serialize,
51 .destroy = lttng_evaluation_session_rotation_destroy,
52};
53
54static
55bool is_rotation_condition(const struct lttng_condition *condition)
56{
57 enum lttng_condition_type type = lttng_condition_get_type(condition);
58
59 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
60 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
61}
62
63static
64bool is_rotation_evaluation(const struct lttng_evaluation *evaluation)
65{
66 enum lttng_condition_type type = lttng_evaluation_get_type(evaluation);
67
68 return type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING ||
69 type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED;
70}
71
72static
73bool lttng_condition_session_rotation_validate(
74 const struct lttng_condition *condition)
75{
76 bool valid = false;
77 struct lttng_condition_session_rotation *rotation;
78
79 if (!condition) {
80 goto end;
81 }
82
83 rotation = container_of(condition,
84 struct lttng_condition_session_rotation, parent);
85 if (!rotation->session_name) {
86 ERR("Invalid session rotation condition: a target session name must be set.");
87 goto end;
88 }
89
90 valid = true;
91end:
92 return valid;
93}
94
95static
96int lttng_condition_session_rotation_serialize(
97 const struct lttng_condition *condition,
c0a66c84 98 struct lttng_payload *payload)
c19092cd
JG
99{
100 int ret;
101 size_t session_name_len;
102 struct lttng_condition_session_rotation *rotation;
103 struct lttng_condition_session_rotation_comm rotation_comm;
104
105 if (!condition || !is_rotation_condition(condition)) {
106 ret = -1;
107 goto end;
108 }
109
110 DBG("Serializing session rotation condition");
111 rotation = container_of(condition, struct lttng_condition_session_rotation,
112 parent);
113
114 session_name_len = strlen(rotation->session_name) + 1;
115 if (session_name_len > LTTNG_NAME_MAX) {
116 ret = -1;
117 goto end;
118 }
119
120 rotation_comm.session_name_len = session_name_len;
c0a66c84 121 ret = lttng_dynamic_buffer_append(&payload->buffer, &rotation_comm,
c19092cd
JG
122 sizeof(rotation_comm));
123 if (ret) {
124 goto end;
125 }
c0a66c84
JG
126 ret = lttng_dynamic_buffer_append(&payload->buffer,
127 rotation->session_name, session_name_len);
c19092cd
JG
128 if (ret) {
129 goto end;
130 }
131end:
132 return ret;
133}
134
135static
136bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
137 const struct lttng_condition *_b)
138{
139 bool is_equal = false;
140 struct lttng_condition_session_rotation *a, *b;
141
142 a = container_of(_a, struct lttng_condition_session_rotation, parent);
143 b = container_of(_b, struct lttng_condition_session_rotation, parent);
144
145 /* Both session names must be set or both must be unset. */
146 if ((a->session_name && !b->session_name) ||
147 (!a->session_name && b->session_name)) {
148 WARN("Comparing session rotation conditions with uninitialized session names.");
149 goto end;
150 }
151
152 if (a->session_name && b->session_name &&
153 strcmp(a->session_name, b->session_name)) {
154 goto end;
155 }
156
157 is_equal = true;
158end:
159 return is_equal;
160}
161
162static
163void lttng_condition_session_rotation_destroy(
164 struct lttng_condition *condition)
165{
166 struct lttng_condition_session_rotation *rotation;
167
168 rotation = container_of(condition,
169 struct lttng_condition_session_rotation, parent);
170
171 free(rotation->session_name);
172 free(rotation);
173}
174
175static
176struct lttng_condition *lttng_condition_session_rotation_create(
177 enum lttng_condition_type type)
178{
179 struct lttng_condition_session_rotation *condition;
180
181 condition = zmalloc(sizeof(struct lttng_condition_session_rotation));
182 if (!condition) {
183 return NULL;
184 }
185
186 memcpy(&condition->parent, &rotation_condition_template,
a38478c9 187 sizeof(condition->parent));
c19092cd
JG
188 lttng_condition_init(&condition->parent, type);
189 return &condition->parent;
190}
191
192struct lttng_condition *lttng_condition_session_rotation_ongoing_create(void)
193{
194 return lttng_condition_session_rotation_create(
195 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
196}
197
198struct lttng_condition *lttng_condition_session_rotation_completed_create(void)
199{
200 return lttng_condition_session_rotation_create(
201 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
202}
203
204static
c0a66c84
JG
205ssize_t init_condition_from_payload(struct lttng_condition *condition,
206 struct lttng_payload_view *src_view)
c19092cd
JG
207{
208 ssize_t ret, condition_size;
209 enum lttng_condition_status status;
c19092cd
JG
210 const char *session_name;
211 struct lttng_buffer_view name_view;
3e6e0df2
JG
212 const struct lttng_condition_session_rotation_comm *condition_comm;
213 struct lttng_payload_view condition_comm_view =
214 lttng_payload_view_from_view(
215 src_view, 0, sizeof(*condition_comm));
c19092cd 216
3e6e0df2 217 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
c19092cd
JG
218 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
219 ret = -1;
220 goto end;
221 }
222
c0a66c84
JG
223 condition_comm = (typeof(condition_comm)) src_view->buffer.data;
224 name_view = lttng_buffer_view_from_view(&src_view->buffer,
3e6e0df2 225 sizeof(*condition_comm), condition_comm->session_name_len);
c19092cd 226
3e6e0df2
JG
227 if (!lttng_buffer_view_is_valid(&name_view)) {
228 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain session name");
c19092cd
JG
229 ret = -1;
230 goto end;
231 }
232
3e6e0df2
JG
233 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
234 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
c19092cd
JG
235 ret = -1;
236 goto end;
237 }
238
239 session_name = name_view.data;
240 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
241 ERR("Malformed session name encountered in condition buffer");
242 ret = -1;
243 goto end;
244 }
245
246 status = lttng_condition_session_rotation_set_session_name(condition,
247 session_name);
248 if (status != LTTNG_CONDITION_STATUS_OK) {
249 ERR("Failed to set buffer consumed session name");
250 ret = -1;
251 goto end;
252 }
253
254 if (!lttng_condition_validate(condition)) {
255 ret = -1;
256 goto end;
257 }
258
259 condition_size = sizeof(*condition_comm) +
260 (ssize_t) condition_comm->session_name_len;
261 ret = condition_size;
262end:
263 return ret;
264}
265
266static
c0a66c84
JG
267ssize_t lttng_condition_session_rotation_create_from_payload(
268 struct lttng_payload_view *view,
c19092cd
JG
269 struct lttng_condition **_condition,
270 enum lttng_condition_type type)
271{
272 ssize_t ret;
273 struct lttng_condition *condition = NULL;
274
275 switch (type) {
276 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
277 condition = lttng_condition_session_rotation_ongoing_create();
278 break;
279 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
280 condition = lttng_condition_session_rotation_completed_create();
281 break;
282 default:
283 ret = -1;
284 goto error;
285 }
286
287 if (!_condition || !condition) {
288 ret = -1;
289 goto error;
290 }
291
c0a66c84 292 ret = init_condition_from_payload(condition, view);
c19092cd
JG
293 if (ret < 0) {
294 goto error;
295 }
296
297 *_condition = condition;
298 return ret;
299error:
300 lttng_condition_destroy(condition);
301 return ret;
302}
303
304LTTNG_HIDDEN
c0a66c84
JG
305ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
306 struct lttng_payload_view *view,
c19092cd
JG
307 struct lttng_condition **condition)
308{
c0a66c84 309 return lttng_condition_session_rotation_create_from_payload(view,
c19092cd
JG
310 condition,
311 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
312}
313
314LTTNG_HIDDEN
c0a66c84
JG
315ssize_t lttng_condition_session_rotation_completed_create_from_payload(
316 struct lttng_payload_view *view,
c19092cd
JG
317 struct lttng_condition **condition)
318{
c0a66c84 319 return lttng_condition_session_rotation_create_from_payload(view,
c19092cd
JG
320 condition,
321 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
322}
323
324static
325struct lttng_evaluation *lttng_evaluation_session_rotation_create(
326 enum lttng_condition_type type, uint64_t id,
327 struct lttng_trace_archive_location *location)
328{
329 struct lttng_evaluation_session_rotation *evaluation;
330
331 evaluation = zmalloc(sizeof(struct lttng_evaluation_session_rotation));
332 if (!evaluation) {
333 return NULL;
334 }
335
336 memcpy(&evaluation->parent, &rotation_evaluation_template,
a38478c9 337 sizeof(evaluation->parent));
c19092cd
JG
338 lttng_evaluation_init(&evaluation->parent, type);
339 evaluation->id = id;
340 evaluation->location = location;
341 return &evaluation->parent;
342}
343
344static
c0a66c84 345ssize_t create_evaluation_from_payload(
c19092cd 346 enum lttng_condition_type type,
c0a66c84 347 struct lttng_payload_view *view,
c19092cd
JG
348 struct lttng_evaluation **_evaluation)
349{
350 ssize_t ret, size;
351 struct lttng_evaluation *evaluation = NULL;
352 struct lttng_trace_archive_location *location = NULL;
3e6e0df2
JG
353 const struct lttng_evaluation_session_rotation_comm *comm;
354 struct lttng_payload_view comm_view = lttng_payload_view_from_view(
355 view, 0, sizeof(*comm));
c19092cd 356
3e6e0df2 357 if (!lttng_payload_view_is_valid(&comm_view)) {
c19092cd
JG
358 goto error;
359 }
360
3e6e0df2 361 comm = (typeof(comm)) comm_view.buffer.data;
c19092cd
JG
362 size = sizeof(*comm);
363 if (comm->has_location) {
3e6e0df2
JG
364 const struct lttng_buffer_view location_view =
365 lttng_buffer_view_from_view(
366 &view->buffer, sizeof(*comm), -1);
367
368 if (!lttng_buffer_view_is_valid(&location_view)) {
c19092cd
JG
369 goto error;
370 }
371
372 ret = lttng_trace_archive_location_create_from_buffer(
373 &location_view, &location);
374 if (ret < 0) {
375 goto error;
376 }
377 size += ret;
378 }
379
380 evaluation = lttng_evaluation_session_rotation_create(type, comm->id,
381 location);
382 if (!evaluation) {
383 goto error;
384 }
385
386 ret = size;
387 *_evaluation = evaluation;
388 return ret;
389error:
390 lttng_trace_archive_location_destroy(location);
391 evaluation = NULL;
392 return -1;
393}
394
395static
c0a66c84 396ssize_t lttng_evaluation_session_rotation_create_from_payload(
c19092cd 397 enum lttng_condition_type type,
c0a66c84 398 struct lttng_payload_view *view,
c19092cd
JG
399 struct lttng_evaluation **_evaluation)
400{
401 ssize_t ret;
402 struct lttng_evaluation *evaluation = NULL;
403
404 if (!_evaluation) {
405 ret = -1;
406 goto error;
407 }
408
c0a66c84 409 ret = create_evaluation_from_payload(type, view, &evaluation);
c19092cd
JG
410 if (ret < 0) {
411 goto error;
412 }
413
414 *_evaluation = evaluation;
415 return ret;
416error:
417 lttng_evaluation_destroy(evaluation);
418 return ret;
419}
420
421LTTNG_HIDDEN
c0a66c84
JG
422ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
423 struct lttng_payload_view *view,
c19092cd
JG
424 struct lttng_evaluation **evaluation)
425{
c0a66c84 426 return lttng_evaluation_session_rotation_create_from_payload(
c19092cd
JG
427 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
428 view, evaluation);
429}
430
431LTTNG_HIDDEN
c0a66c84
JG
432ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
433 struct lttng_payload_view *view,
c19092cd
JG
434 struct lttng_evaluation **evaluation)
435{
c0a66c84 436 return lttng_evaluation_session_rotation_create_from_payload(
c19092cd
JG
437 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
438 view, evaluation);
439}
440
441LTTNG_HIDDEN
442struct lttng_evaluation *lttng_evaluation_session_rotation_ongoing_create(
443 uint64_t id)
444{
445 return lttng_evaluation_session_rotation_create(
446 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING, id,
447 NULL);
448}
449
450LTTNG_HIDDEN
451struct lttng_evaluation *lttng_evaluation_session_rotation_completed_create(
452 uint64_t id, struct lttng_trace_archive_location *location)
453{
454 return lttng_evaluation_session_rotation_create(
455 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED, id,
456 location);
457}
458
459enum lttng_condition_status
460lttng_condition_session_rotation_get_session_name(
461 const struct lttng_condition *condition,
462 const char **session_name)
463{
464 struct lttng_condition_session_rotation *rotation;
465 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
466
467 if (!condition || !is_rotation_condition(condition) || !session_name) {
468 status = LTTNG_CONDITION_STATUS_INVALID;
469 goto end;
470 }
471
472 rotation = container_of(condition, struct lttng_condition_session_rotation,
473 parent);
474 if (!rotation->session_name) {
475 status = LTTNG_CONDITION_STATUS_UNSET;
476 goto end;
477 }
478 *session_name = rotation->session_name;
479end:
480 return status;
481}
482
483enum lttng_condition_status
484lttng_condition_session_rotation_set_session_name(
485 struct lttng_condition *condition, const char *session_name)
486{
487 char *session_name_copy;
488 struct lttng_condition_session_rotation *rotation;
489 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
490
491 if (!condition || !is_rotation_condition(condition) ||
492 !session_name || strlen(session_name) == 0) {
493 status = LTTNG_CONDITION_STATUS_INVALID;
494 goto end;
495 }
496
497 rotation = container_of(condition,
498 struct lttng_condition_session_rotation, parent);
499 session_name_copy = strdup(session_name);
500 if (!session_name_copy) {
501 status = LTTNG_CONDITION_STATUS_ERROR;
502 goto end;
503 }
504
505 free(rotation->session_name);
506 rotation->session_name = session_name_copy;
507end:
508 return status;
509}
510
511static
512int lttng_evaluation_session_rotation_serialize(
513 const struct lttng_evaluation *evaluation,
c0a66c84 514 struct lttng_payload *payload)
c19092cd
JG
515{
516 int ret;
517 struct lttng_evaluation_session_rotation *rotation;
518 struct lttng_evaluation_session_rotation_comm comm = { 0 };
519
520 rotation = container_of(evaluation,
521 struct lttng_evaluation_session_rotation, parent);
522 comm.id = rotation->id;
523 comm.has_location = !!rotation->location;
c0a66c84
JG
524 ret = lttng_dynamic_buffer_append(
525 &payload->buffer, &comm, sizeof(comm));
c19092cd
JG
526 if (ret) {
527 goto end;
528 }
529 if (!rotation->location) {
530 goto end;
531 }
532 ret = lttng_trace_archive_location_serialize(rotation->location,
c0a66c84 533 &payload->buffer);
c19092cd
JG
534end:
535 return ret;
536}
537
538static
539void lttng_evaluation_session_rotation_destroy(
540 struct lttng_evaluation *evaluation)
541{
542 struct lttng_evaluation_session_rotation *rotation;
543
544 rotation = container_of(evaluation,
545 struct lttng_evaluation_session_rotation, parent);
546 lttng_trace_archive_location_destroy(rotation->location);
547 free(rotation);
548}
549
550enum lttng_evaluation_status
551lttng_evaluation_session_rotation_get_id(
552 const struct lttng_evaluation *evaluation, uint64_t *id)
553{
554 const struct lttng_evaluation_session_rotation *rotation;
555 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
556
557 if (!evaluation || !id || !is_rotation_evaluation(evaluation)) {
558 status = LTTNG_EVALUATION_STATUS_INVALID;
559 goto end;
560 }
561
562 rotation = container_of(evaluation,
563 struct lttng_evaluation_session_rotation, parent);
564 *id = rotation->id;
565end:
566 return status;
567}
568
569enum lttng_evaluation_status
570lttng_evaluation_session_rotation_completed_get_location(
571 const struct lttng_evaluation *evaluation,
572 const struct lttng_trace_archive_location **location)
573{
574 const struct lttng_evaluation_session_rotation *rotation;
575 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
576
577 if (!evaluation || !location ||
578 evaluation->type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
579 status = LTTNG_EVALUATION_STATUS_INVALID;
580 goto end;
581 }
582
583 rotation = container_of(evaluation,
584 struct lttng_evaluation_session_rotation, parent);
585 *location = rotation->location;
586end:
587 return status;
588}
This page took 0.0859 seconds and 4 git commands to generate.