Fix: unchecked buffer size for communication header
[lttng-tools.git] / src / common / session-consumed-size.c
CommitLineData
e8360425 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
e8360425 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
e8360425 5 *
e8360425
JD
6 */
7
8#include <lttng/condition/condition-internal.h>
9#include <lttng/condition/session-consumed-size-internal.h>
319370bd 10#include <lttng/constant.h>
e8360425
JD
11#include <common/macros.h>
12#include <common/error.h>
13#include <assert.h>
14#include <math.h>
15#include <float.h>
16#include <time.h>
17
18#define IS_CONSUMED_SIZE_CONDITION(condition) ( \
19 lttng_condition_get_type(condition) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \
20 )
21
22#define IS_CONSUMED_SIZE_EVALUATION(evaluation) ( \
23 lttng_evaluation_get_type(evaluation) == LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE \
24 )
25
26static
27void lttng_condition_session_consumed_size_destroy(struct lttng_condition *condition)
28{
29 struct lttng_condition_session_consumed_size *consumed_size;
30
31 consumed_size = container_of(condition,
32 struct lttng_condition_session_consumed_size, parent);
33
34 free(consumed_size->session_name);
35 free(consumed_size);
36}
37
38static
39bool lttng_condition_session_consumed_size_validate(
40 const struct lttng_condition *condition)
41{
42 bool valid = false;
43 struct lttng_condition_session_consumed_size *consumed;
44
45 if (!condition) {
46 goto end;
47 }
48
49 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
50 parent);
51 if (!consumed->session_name) {
9ef5b6be 52 ERR("Invalid session consumed size condition: a target session name must be set.");
e8360425
JD
53 goto end;
54 }
55 if (!consumed->consumed_threshold_bytes.set) {
9ef5b6be 56 ERR("Invalid session consumed size condition: a threshold must be set.");
e8360425
JD
57 goto end;
58 }
59
60 valid = true;
61end:
62 return valid;
63}
64
65static
3647288f
JG
66int lttng_condition_session_consumed_size_serialize(
67 const struct lttng_condition *condition,
c0a66c84 68 struct lttng_payload *payload)
e8360425 69{
3647288f 70 int ret;
e8360425 71 size_t session_name_len;
3647288f
JG
72 struct lttng_condition_session_consumed_size *consumed;
73 struct lttng_condition_session_consumed_size_comm consumed_comm;
e8360425
JD
74
75 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) {
76 ret = -1;
77 goto end;
78 }
79
3647288f
JG
80 DBG("Serializing session consumed size condition");
81 consumed = container_of(condition,
82 struct lttng_condition_session_consumed_size,
e8360425 83 parent);
3647288f 84
e8360425
JD
85 session_name_len = strlen(consumed->session_name) + 1;
86 if (session_name_len > LTTNG_NAME_MAX) {
87 ret = -1;
88 goto end;
89 }
3647288f
JG
90
91 consumed_comm.consumed_threshold_bytes =
92 consumed->consumed_threshold_bytes.value;
93 consumed_comm.session_name_len = (uint32_t) session_name_len;
94
c0a66c84 95 ret = lttng_dynamic_buffer_append(&payload->buffer, &consumed_comm,
3647288f
JG
96 sizeof(consumed_comm));
97 if (ret) {
98 goto end;
99 }
c0a66c84
JG
100
101 ret = lttng_dynamic_buffer_append(&payload->buffer, consumed->session_name,
3647288f
JG
102 session_name_len);
103 if (ret) {
104 goto end;
e8360425 105 }
e8360425
JD
106end:
107 return ret;
108}
109
110static
111bool lttng_condition_session_consumed_size_is_equal(const struct lttng_condition *_a,
112 const struct lttng_condition *_b)
113{
114 bool is_equal = false;
115 struct lttng_condition_session_consumed_size *a, *b;
116
117 a = container_of(_a, struct lttng_condition_session_consumed_size, parent);
118 b = container_of(_b, struct lttng_condition_session_consumed_size, parent);
119
120 if (a->consumed_threshold_bytes.set && b->consumed_threshold_bytes.set) {
121 uint64_t a_value, b_value;
122
123 a_value = a->consumed_threshold_bytes.value;
124 b_value = b->consumed_threshold_bytes.value;
125 if (a_value != b_value) {
126 goto end;
127 }
128 }
129
821d5e92
JG
130 assert(a->session_name);
131 assert(b->session_name);
132 if (strcmp(a->session_name, b->session_name)) {
e8360425
JD
133 goto end;
134 }
135
136 is_equal = true;
137end:
138 return is_equal;
139}
140
141struct lttng_condition *lttng_condition_session_consumed_size_create(void)
142{
143 struct lttng_condition_session_consumed_size *condition;
144
145 condition = zmalloc(sizeof(struct lttng_condition_session_consumed_size));
146 if (!condition) {
147 return NULL;
148 }
149
150 lttng_condition_init(&condition->parent, LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE);
151 condition->parent.validate = lttng_condition_session_consumed_size_validate;
152 condition->parent.serialize = lttng_condition_session_consumed_size_serialize;
153 condition->parent.equal = lttng_condition_session_consumed_size_is_equal;
154 condition->parent.destroy = lttng_condition_session_consumed_size_destroy;
155 return &condition->parent;
156}
157
158static
c0a66c84
JG
159ssize_t init_condition_from_payload(struct lttng_condition *condition,
160 struct lttng_payload_view *src_view)
e8360425
JD
161{
162 ssize_t ret, condition_size;
163 enum lttng_condition_status status;
e8360425 164 const char *session_name;
3e6e0df2
JG
165 struct lttng_buffer_view session_name_view;
166 const struct lttng_condition_session_consumed_size_comm *condition_comm;
167 struct lttng_payload_view condition_comm_view = lttng_payload_view_from_view(
168 src_view, 0, sizeof(*condition_comm));
e8360425 169
3e6e0df2 170 if (!lttng_payload_view_is_valid(&condition_comm_view)) {
e8360425
JD
171 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain header");
172 ret = -1;
173 goto end;
174 }
175
3e6e0df2
JG
176 condition_comm = (typeof(condition_comm)) condition_comm_view.buffer.data;
177 session_name_view = lttng_buffer_view_from_view(&src_view->buffer,
178 sizeof(*condition_comm), condition_comm->session_name_len);
e8360425
JD
179
180 if (condition_comm->session_name_len > LTTNG_NAME_MAX) {
181 ERR("Failed to initialize from malformed condition buffer: name exceeds LTTNG_MAX_NAME");
182 ret = -1;
183 goto end;
184 }
185
3e6e0df2 186 if (!lttng_buffer_view_is_valid(&session_name_view)) {
e8360425
JD
187 ERR("Failed to initialize from malformed condition buffer: buffer too short to contain element names");
188 ret = -1;
189 goto end;
190 }
191
192 status = lttng_condition_session_consumed_size_set_threshold(condition,
193 condition_comm->consumed_threshold_bytes);
194 if (status != LTTNG_CONDITION_STATUS_OK) {
9ef5b6be 195 ERR("Failed to initialize session consumed size condition threshold");
e8360425
JD
196 ret = -1;
197 goto end;
198 }
199
3e6e0df2 200 session_name = session_name_view.data;
e8360425
JD
201 if (*(session_name + condition_comm->session_name_len - 1) != '\0') {
202 ERR("Malformed session name encountered in condition buffer");
203 ret = -1;
204 goto end;
205 }
206
207 status = lttng_condition_session_consumed_size_set_session_name(condition,
208 session_name);
209 if (status != LTTNG_CONDITION_STATUS_OK) {
9ef5b6be 210 ERR("Failed to set session consumed size condition's session name");
e8360425
JD
211 ret = -1;
212 goto end;
213 }
214
215 if (!lttng_condition_validate(condition)) {
216 ret = -1;
217 goto end;
218 }
219
220 condition_size = sizeof(*condition_comm) +
221 (ssize_t) condition_comm->session_name_len;
222 ret = condition_size;
223end:
224 return ret;
225}
226
227LTTNG_HIDDEN
c0a66c84
JG
228ssize_t lttng_condition_session_consumed_size_create_from_payload(
229 struct lttng_payload_view *view,
e8360425
JD
230 struct lttng_condition **_condition)
231{
232 ssize_t ret;
233 struct lttng_condition *condition =
234 lttng_condition_session_consumed_size_create();
235
236 if (!_condition || !condition) {
237 ret = -1;
238 goto error;
239 }
240
c0a66c84 241 ret = init_condition_from_payload(condition, view);
e8360425
JD
242 if (ret < 0) {
243 goto error;
244 }
245
246 *_condition = condition;
247 return ret;
248error:
249 lttng_condition_destroy(condition);
250 return ret;
251}
252
253static
c0a66c84
JG
254struct lttng_evaluation *create_evaluation_from_payload(
255 const struct lttng_payload_view *view)
e8360425
JD
256{
257 const struct lttng_evaluation_session_consumed_size_comm *comm =
c0a66c84 258 (typeof(comm)) view->buffer.data;
e8360425
JD
259 struct lttng_evaluation *evaluation = NULL;
260
c0a66c84 261 if (view->buffer.size < sizeof(*comm)) {
e8360425
JD
262 goto end;
263 }
264
5f2c1c0f 265 evaluation = lttng_evaluation_session_consumed_size_create(
e8360425
JD
266 comm->session_consumed);
267end:
268 return evaluation;
269}
270
271LTTNG_HIDDEN
c0a66c84
JG
272ssize_t lttng_evaluation_session_consumed_size_create_from_payload(
273 struct lttng_payload_view *view,
e8360425
JD
274 struct lttng_evaluation **_evaluation)
275{
276 ssize_t ret;
277 struct lttng_evaluation *evaluation = NULL;
278
279 if (!_evaluation) {
280 ret = -1;
281 goto error;
282 }
283
c0a66c84 284 evaluation = create_evaluation_from_payload(view);
e8360425
JD
285 if (!evaluation) {
286 ret = -1;
287 goto error;
288 }
289
290 *_evaluation = evaluation;
291 ret = sizeof(struct lttng_evaluation_session_consumed_size_comm);
292 return ret;
293error:
294 lttng_evaluation_destroy(evaluation);
295 return ret;
296}
297
298enum lttng_condition_status
299lttng_condition_session_consumed_size_get_threshold(
300 const struct lttng_condition *condition,
301 uint64_t *consumed_threshold_bytes)
302{
303 struct lttng_condition_session_consumed_size *consumed;
304 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
305
306 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !consumed_threshold_bytes) {
307 status = LTTNG_CONDITION_STATUS_INVALID;
308 goto end;
309 }
310
311 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
312 parent);
313 if (!consumed->consumed_threshold_bytes.set) {
314 status = LTTNG_CONDITION_STATUS_UNSET;
315 goto end;
316 }
317 *consumed_threshold_bytes = consumed->consumed_threshold_bytes.value;
318end:
319 return status;
320}
321
322enum lttng_condition_status
323lttng_condition_session_consumed_size_set_threshold(
324 struct lttng_condition *condition, uint64_t consumed_threshold_bytes)
325{
326 struct lttng_condition_session_consumed_size *consumed;
327 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
328
329 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition)) {
330 status = LTTNG_CONDITION_STATUS_INVALID;
331 goto end;
332 }
333
334 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
335 parent);
336 consumed->consumed_threshold_bytes.set = true;
337 consumed->consumed_threshold_bytes.value = consumed_threshold_bytes;
338end:
339 return status;
340}
341
342enum lttng_condition_status
343lttng_condition_session_consumed_size_get_session_name(
344 const struct lttng_condition *condition,
345 const char **session_name)
346{
347 struct lttng_condition_session_consumed_size *consumed;
348 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
349
350 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) || !session_name) {
351 status = LTTNG_CONDITION_STATUS_INVALID;
352 goto end;
353 }
354
355 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
356 parent);
357 if (!consumed->session_name) {
358 status = LTTNG_CONDITION_STATUS_UNSET;
359 goto end;
360 }
361 *session_name = consumed->session_name;
362end:
363 return status;
364}
365
366enum lttng_condition_status
367lttng_condition_session_consumed_size_set_session_name(
368 struct lttng_condition *condition, const char *session_name)
369{
370 char *session_name_copy;
371 struct lttng_condition_session_consumed_size *consumed;
372 enum lttng_condition_status status = LTTNG_CONDITION_STATUS_OK;
373
374 if (!condition || !IS_CONSUMED_SIZE_CONDITION(condition) ||
375 !session_name || strlen(session_name) == 0) {
376 status = LTTNG_CONDITION_STATUS_INVALID;
377 goto end;
378 }
379
380 consumed = container_of(condition, struct lttng_condition_session_consumed_size,
381 parent);
382 session_name_copy = strdup(session_name);
383 if (!session_name_copy) {
384 status = LTTNG_CONDITION_STATUS_ERROR;
385 goto end;
386 }
387
388 if (consumed->session_name) {
389 free(consumed->session_name);
390 }
391 consumed->session_name = session_name_copy;
392end:
393 return status;
394}
395
396static
3647288f 397int lttng_evaluation_session_consumed_size_serialize(
9b63a4aa 398 const struct lttng_evaluation *evaluation,
c0a66c84 399 struct lttng_payload *payload)
e8360425 400{
e8360425 401 struct lttng_evaluation_session_consumed_size *consumed;
3647288f 402 struct lttng_evaluation_session_consumed_size_comm comm;
e8360425 403
c0a66c84
JG
404 consumed = container_of(evaluation,
405 struct lttng_evaluation_session_consumed_size, parent);
3647288f 406 comm.session_consumed = consumed->session_consumed;
c0a66c84
JG
407 return lttng_dynamic_buffer_append(
408 &payload->buffer, &comm, sizeof(comm));
e8360425
JD
409}
410
411static
412void lttng_evaluation_session_consumed_size_destroy(
413 struct lttng_evaluation *evaluation)
414{
415 struct lttng_evaluation_session_consumed_size *consumed;
416
417 consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size,
418 parent);
419 free(consumed);
420}
421
422LTTNG_HIDDEN
423struct lttng_evaluation *lttng_evaluation_session_consumed_size_create(
5f2c1c0f 424 uint64_t consumed)
e8360425
JD
425{
426 struct lttng_evaluation_session_consumed_size *consumed_eval;
427
428 consumed_eval = zmalloc(sizeof(struct lttng_evaluation_session_consumed_size));
429 if (!consumed_eval) {
430 goto end;
431 }
432
5f2c1c0f 433 consumed_eval->parent.type = LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE;
e8360425
JD
434 consumed_eval->session_consumed = consumed;
435 consumed_eval->parent.serialize = lttng_evaluation_session_consumed_size_serialize;
436 consumed_eval->parent.destroy = lttng_evaluation_session_consumed_size_destroy;
437end:
438 return &consumed_eval->parent;
439}
440
441enum lttng_evaluation_status
442lttng_evaluation_session_consumed_size_get_consumed_size(
443 const struct lttng_evaluation *evaluation,
444 uint64_t *session_consumed)
445{
446 struct lttng_evaluation_session_consumed_size *consumed;
447 enum lttng_evaluation_status status = LTTNG_EVALUATION_STATUS_OK;
448
449 if (!evaluation || !IS_CONSUMED_SIZE_EVALUATION(evaluation) ||
450 !session_consumed) {
451 status = LTTNG_EVALUATION_STATUS_INVALID;
452 goto end;
453 }
454
455 consumed = container_of(evaluation, struct lttng_evaluation_session_consumed_size,
456 parent);
457 *session_consumed = consumed->session_consumed;
458end:
459 return status;
460}
This page took 0.050356 seconds and 4 git commands to generate.