Fix: unchecked buffer size for communication header
[lttng-tools.git] / src / common / session-rotation.c
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
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
16 static
17 bool lttng_condition_session_rotation_validate(
18 const struct lttng_condition *condition);
19 static
20 int lttng_condition_session_rotation_serialize(
21 const struct lttng_condition *condition,
22 struct lttng_payload *payload);
23 static
24 bool lttng_condition_session_rotation_is_equal(const struct lttng_condition *_a,
25 const struct lttng_condition *_b);
26 static
27 void lttng_condition_session_rotation_destroy(
28 struct lttng_condition *condition);
29
30 static const
31 struct 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
39 static
40 int lttng_evaluation_session_rotation_serialize(
41 const struct lttng_evaluation *evaluation,
42 struct lttng_payload *payload);
43 static
44 void lttng_evaluation_session_rotation_destroy(
45 struct lttng_evaluation *evaluation);
46
47 static const
48 struct 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
54 static
55 bool 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
63 static
64 bool 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
72 static
73 bool 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;
91 end:
92 return valid;
93 }
94
95 static
96 int lttng_condition_session_rotation_serialize(
97 const struct lttng_condition *condition,
98 struct lttng_payload *payload)
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;
121 ret = lttng_dynamic_buffer_append(&payload->buffer, &rotation_comm,
122 sizeof(rotation_comm));
123 if (ret) {
124 goto end;
125 }
126 ret = lttng_dynamic_buffer_append(&payload->buffer,
127 rotation->session_name, session_name_len);
128 if (ret) {
129 goto end;
130 }
131 end:
132 return ret;
133 }
134
135 static
136 bool 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;
158 end:
159 return is_equal;
160 }
161
162 static
163 void 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
175 static
176 struct 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,
187 sizeof(condition->parent));
188 lttng_condition_init(&condition->parent, type);
189 return &condition->parent;
190 }
191
192 struct 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
198 struct 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
204 static
205 ssize_t init_condition_from_payload(struct lttng_condition *condition,
206 struct lttng_payload_view *src_view)
207 {
208 ssize_t ret, condition_size;
209 enum lttng_condition_status status;
210 const char *session_name;
211 struct lttng_buffer_view name_view;
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));
216
217 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
218 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
219 ret = -1;
220 goto end;
221 }
222
223 condition_comm = (typeof(condition_comm)) src_view->buffer.data;
224 name_view = lttng_buffer_view_from_view(&src_view->buffer,
225 sizeof(*condition_comm), condition_comm->session_name_len);
226
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");
229 ret = -1;
230 goto end;
231 }
232
233 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
234 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
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;
262 end:
263 return ret;
264 }
265
266 static
267 ssize_t lttng_condition_session_rotation_create_from_payload(
268 struct lttng_payload_view *view,
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
292 ret = init_condition_from_payload(condition, view);
293 if (ret < 0) {
294 goto error;
295 }
296
297 *_condition = condition;
298 return ret;
299 error:
300 lttng_condition_destroy(condition);
301 return ret;
302 }
303
304 LTTNG_HIDDEN
305 ssize_t lttng_condition_session_rotation_ongoing_create_from_payload(
306 struct lttng_payload_view *view,
307 struct lttng_condition **condition)
308 {
309 return lttng_condition_session_rotation_create_from_payload(view,
310 condition,
311 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING);
312 }
313
314 LTTNG_HIDDEN
315 ssize_t lttng_condition_session_rotation_completed_create_from_payload(
316 struct lttng_payload_view *view,
317 struct lttng_condition **condition)
318 {
319 return lttng_condition_session_rotation_create_from_payload(view,
320 condition,
321 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED);
322 }
323
324 static
325 struct 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,
337 sizeof(evaluation->parent));
338 lttng_evaluation_init(&evaluation->parent, type);
339 evaluation->id = id;
340 evaluation->location = location;
341 return &evaluation->parent;
342 }
343
344 static
345 ssize_t create_evaluation_from_payload(
346 enum lttng_condition_type type,
347 struct lttng_payload_view *view,
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;
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));
356
357 if (!lttng_payload_view_is_valid(&comm_view)) {
358 goto error;
359 }
360
361 comm = (typeof(comm)) comm_view.buffer.data;
362 size = sizeof(*comm);
363 if (comm->has_location) {
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)) {
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;
389 error:
390 lttng_trace_archive_location_destroy(location);
391 evaluation = NULL;
392 return -1;
393 }
394
395 static
396 ssize_t lttng_evaluation_session_rotation_create_from_payload(
397 enum lttng_condition_type type,
398 struct lttng_payload_view *view,
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
409 ret = create_evaluation_from_payload(type, view, &evaluation);
410 if (ret < 0) {
411 goto error;
412 }
413
414 *_evaluation = evaluation;
415 return ret;
416 error:
417 lttng_evaluation_destroy(evaluation);
418 return ret;
419 }
420
421 LTTNG_HIDDEN
422 ssize_t lttng_evaluation_session_rotation_ongoing_create_from_payload(
423 struct lttng_payload_view *view,
424 struct lttng_evaluation **evaluation)
425 {
426 return lttng_evaluation_session_rotation_create_from_payload(
427 LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING,
428 view, evaluation);
429 }
430
431 LTTNG_HIDDEN
432 ssize_t lttng_evaluation_session_rotation_completed_create_from_payload(
433 struct lttng_payload_view *view,
434 struct lttng_evaluation **evaluation)
435 {
436 return lttng_evaluation_session_rotation_create_from_payload(
437 LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED,
438 view, evaluation);
439 }
440
441 LTTNG_HIDDEN
442 struct 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
450 LTTNG_HIDDEN
451 struct 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
459 enum lttng_condition_status
460 lttng_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;
479 end:
480 return status;
481 }
482
483 enum lttng_condition_status
484 lttng_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;
507 end:
508 return status;
509 }
510
511 static
512 int lttng_evaluation_session_rotation_serialize(
513 const struct lttng_evaluation *evaluation,
514 struct lttng_payload *payload)
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;
524 ret = lttng_dynamic_buffer_append(
525 &payload->buffer, &comm, sizeof(comm));
526 if (ret) {
527 goto end;
528 }
529 if (!rotation->location) {
530 goto end;
531 }
532 ret = lttng_trace_archive_location_serialize(rotation->location,
533 &payload->buffer);
534 end:
535 return ret;
536 }
537
538 static
539 void 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
550 enum lttng_evaluation_status
551 lttng_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;
565 end:
566 return status;
567 }
568
569 enum lttng_evaluation_status
570 lttng_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;
586 end:
587 return status;
588 }
This page took 0.040666 seconds and 4 git commands to generate.