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