SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / common / event-rule-uprobe.c
CommitLineData
1831ae68
FD
1/*
2 * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18#include <lttng/event-rule/event-rule-internal.h>
19#include <lttng/event-rule/uprobe-internal.h>
20#include <lttng/userspace-probe-internal.h>
21#include <common/macros.h>
22#include <common/error.h>
23#include <common/runas.h>
24#include <assert.h>
25
26#define IS_UPROBE_EVENT_RULE(rule) ( \
27 lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_UPROBE \
28 )
29
30static
31void lttng_event_rule_uprobe_destroy(struct lttng_event_rule *rule)
32{
33 struct lttng_event_rule_uprobe *uprobe;
34
35 uprobe = container_of(rule, struct lttng_event_rule_uprobe,
36 parent);
37
38 lttng_userspace_probe_location_destroy(uprobe->location);
39 free(uprobe->name);
40 free(uprobe);
41}
42
43static
44bool lttng_event_rule_uprobe_validate(
45 const struct lttng_event_rule *rule)
46{
47 bool valid = false;
48 struct lttng_event_rule_uprobe *uprobe;
49
50 if (!rule) {
51 goto end;
52 }
53
54 uprobe = container_of(rule, struct lttng_event_rule_uprobe,
55 parent);
56
57 /* Required field */
58 if (!uprobe->name) {
59 ERR("Invalid uprobe event rule: a pattern must be set.");
60 goto end;
61 }
62
63 if (!uprobe->location) {
64 ERR("Invalid uprobe event rule: a location must be set.");
65 goto end;
66 }
67
68 /* TODO should we validate the probe location? */
69
70 valid = true;
71end:
72 return valid;
73}
74
75static
76int lttng_event_rule_uprobe_serialize(
77 const struct lttng_event_rule *rule,
78 struct lttng_dynamic_buffer *buf,
79 int *fd_to_send)
80{
81 int ret;
82 size_t name_len, header_offset, size_before_probe;
83 struct lttng_event_rule_uprobe *uprobe;
84 struct lttng_event_rule_uprobe_comm uprobe_comm = { 0 };
85 struct lttng_event_rule_uprobe_comm *header;
86
87 if (!rule || !IS_UPROBE_EVENT_RULE(rule)) {
88 ret = -1;
89 goto end;
90 }
91
92 header_offset = buf->size;
93
94 DBG("Serializing uprobe event rule");
95 uprobe = container_of(
96 rule, struct lttng_event_rule_uprobe, parent);
97
98 name_len = strlen(uprobe->name) + 1;
99
100 uprobe_comm.name_len = name_len;
101
102 ret = lttng_dynamic_buffer_append(
103 buf, &uprobe_comm, sizeof(uprobe_comm));
104 if (ret) {
105 goto end;
106 }
107 ret = lttng_dynamic_buffer_append(buf, uprobe->name,
108 name_len);
109 if (ret) {
110 goto end;
111 }
112
113 size_before_probe = buf->size;
114
115 /* This serialize return the size taken in the buffer */
116 /* TODO: should all serialize standardise on this? */
117 ret = lttng_userspace_probe_location_serialize(
118 uprobe->location, buf, fd_to_send);
119 if (ret < 0) {
120 goto end;
121 }
122
123 /* Update the header regarding the probe size */
124 header = (struct lttng_event_rule_uprobe_comm *) ((char *) buf->data + header_offset);
125 header->location_len = buf->size - size_before_probe;
126
127 ret = 0;
128
129end:
130 return ret;
131}
132
133static
134bool lttng_event_rule_uprobe_is_equal(const struct lttng_event_rule *_a,
135 const struct lttng_event_rule *_b)
136{
137 bool is_equal = false;
138 struct lttng_event_rule_uprobe *a, *b;
139
140 a = container_of(_a, struct lttng_event_rule_uprobe, parent);
141 b = container_of(_b, struct lttng_event_rule_uprobe, parent);
142
143 /* uprobe is invalid if this is not true */
144 assert(a->name);
145 assert(b->name);
146 if (strcmp(a->name, b->name)) {
147 goto end;
148 }
149
150 assert(a->location);
151 assert(b->location);
152 is_equal = lttng_userspace_probe_location_is_equal(a->location, b->location);
153end:
154 return is_equal;
155}
156
157static
158enum lttng_error_code lttng_event_rule_uprobe_populate(struct lttng_event_rule *rule, uid_t uid, gid_t gid)
159{
160 /* Nothing to do */
161 return LTTNG_OK;
162}
163
164static const char *lttng_event_rule_uprobe_get_filter(
165 const struct lttng_event_rule *rule)
166{
167 /* Unsupported */
168 return NULL;
169}
170
171static const struct lttng_filter_bytecode *
172lttng_event_rule_uprobe_get_filter_bytecode(const struct lttng_event_rule *rule)
173{
174 /* Unsupported */
175 return NULL;
176}
177
178static
179struct lttng_event_exclusion *lttng_event_rule_uprobe_generate_exclusions(struct lttng_event_rule *rule)
180{
181 /* Unsupported */
182 return NULL;
183}
184
185struct lttng_event_rule *lttng_event_rule_uprobe_create()
186{
187 struct lttng_event_rule_uprobe *rule;
188
189 rule = zmalloc(sizeof(struct lttng_event_rule_uprobe));
190 if (!rule) {
191 return NULL;
192 }
193
194 lttng_event_rule_init(&rule->parent, LTTNG_EVENT_RULE_TYPE_UPROBE);
195 rule->parent.validate = lttng_event_rule_uprobe_validate;
196 rule->parent.serialize = lttng_event_rule_uprobe_serialize;
197 rule->parent.equal = lttng_event_rule_uprobe_is_equal;
198 rule->parent.destroy = lttng_event_rule_uprobe_destroy;
199 rule->parent.populate = lttng_event_rule_uprobe_populate;
200 rule->parent.get_filter = lttng_event_rule_uprobe_get_filter;
201 rule->parent.get_filter_bytecode = lttng_event_rule_uprobe_get_filter_bytecode;
202 rule->parent.generate_exclusions = lttng_event_rule_uprobe_generate_exclusions;
203 return &rule->parent;
204}
205
206LTTNG_HIDDEN
207ssize_t lttng_event_rule_uprobe_create_from_buffer(
208 const struct lttng_buffer_view *view,
209 struct lttng_event_rule **_event_rule)
210{
211 ssize_t ret, offset = 0;
212 const struct lttng_event_rule_uprobe_comm *uprobe_comm;
213 const char *name;
214 struct lttng_buffer_view current_view;
215 struct lttng_event_rule *rule = NULL;
216 struct lttng_userspace_probe_location *location;
217 struct lttng_event_rule_uprobe *uprobe;
218
219 if (!_event_rule) {
220 ret = -1;
221 goto end;
222 }
223
224 if (view->size < sizeof(*uprobe_comm)) {
225 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
226 ret = -1;
227 goto end;
228 }
229
230 current_view = lttng_buffer_view_from_view(view, offset, sizeof(*uprobe_comm));
231 uprobe_comm = (typeof(uprobe_comm)) current_view.data;
232
233 if(!uprobe_comm) {
234 ret = -1;
235 goto end;
236 }
237
238 rule = lttng_event_rule_uprobe_create();
239 if (!rule) {
240 ERR("Failed to create event rule uprobe");
241 ret = -1;
242 goto end;
243 }
244
245 /* Skip to payload */
246 offset += current_view.size;
247
248 /* Map the name */
249 current_view = lttng_buffer_view_from_view(view, offset, uprobe_comm->name_len);
250 name = current_view.data;
251 if (!name) {
252 ret = -1;
253 goto end;
254 }
255
256 if (uprobe_comm->name_len == 1 ||
257 name[uprobe_comm->name_len - 1] != '\0' ||
258 strlen(name) != uprobe_comm->name_len - 1) {
259 /*
260 * Check that the name is not NULL, is NULL-terminated, and
261 * does not contain a NULL before the last byte.
262 */
263 ret = -1;
264 goto end;
265 }
266
267 /* Skip after the name */
268 offset += uprobe_comm->name_len;
269
270 /* Map the location */
271 current_view = lttng_buffer_view_from_view(view, offset, uprobe_comm->location_len);
272 ret = lttng_userspace_probe_location_create_from_buffer(&current_view, &location);
273 if (ret < 0) {
274 ret = -1;
275 goto end;
276 }
277
278 assert(ret == uprobe_comm->location_len);
279
280 /* Skip after the location */
281 offset += uprobe_comm->location_len;
282
283 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
284 uprobe->location = location;
285
286 (void) lttng_event_rule_uprobe_set_name(rule, name);
287
288 if (!lttng_event_rule_uprobe_validate(rule)) {
289 ret = -1;
290 goto end;
291 }
292
293 *_event_rule = rule;
294 rule = NULL;
295 ret = offset;
296end:
297 lttng_event_rule_destroy(rule);
298 return ret;
299}
300
301enum lttng_event_rule_status lttng_event_rule_uprobe_set_location(
302 struct lttng_event_rule *rule,
303 const struct lttng_userspace_probe_location *location)
304{
305 struct lttng_userspace_probe_location *location_copy = NULL;
306 struct lttng_event_rule_uprobe *uprobe;
307 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
308
309 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !location) {
310 status = LTTNG_EVENT_RULE_STATUS_INVALID;
311 goto end;
312 }
313
314 uprobe = container_of(rule, struct lttng_event_rule_uprobe,
315 parent);
316 location_copy = lttng_userspace_probe_location_copy(location);
317 if (!location_copy) {
318 status = LTTNG_EVENT_RULE_STATUS_ERROR;
319 goto end;
320 }
321
322 if (uprobe->location) {
323 lttng_userspace_probe_location_destroy(uprobe->location);
324 }
325
326 uprobe->location = location_copy;
327 location_copy = NULL;
328end:
329 lttng_userspace_probe_location_destroy(location_copy);
330 return status;
331}
332
333enum lttng_event_rule_status lttng_event_rule_uprobe_get_location(
334 const struct lttng_event_rule *rule,
335 const struct lttng_userspace_probe_location **location)
336{
337 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
338
339 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !location) {
340 status = LTTNG_EVENT_RULE_STATUS_INVALID;
341 goto end;
342 }
343
344 *location = lttng_event_rule_uprobe_get_location_no_const(rule);
345 if (!*location) {
346 status = LTTNG_EVENT_RULE_STATUS_UNSET;
347 goto end;
348 }
349
350end:
351 return status;
352
353}
354
355LTTNG_HIDDEN
356struct lttng_userspace_probe_location *
357lttng_event_rule_uprobe_get_location_no_const(
358 const struct lttng_event_rule *rule)
359{
360 struct lttng_event_rule_uprobe *uprobe;
361 assert(rule);
362 uprobe = container_of(rule, struct lttng_event_rule_uprobe,
363 parent);
364
365 return uprobe->location;
366}
367
368enum lttng_event_rule_status lttng_event_rule_uprobe_set_name(
369 struct lttng_event_rule *rule, const char *name)
370{
371 char *name_copy = NULL;
372 struct lttng_event_rule_uprobe *uprobe;
373 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
374
375 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !name ||
376 strlen(name) == 0) {
377 status = LTTNG_EVENT_RULE_STATUS_INVALID;
378 goto end;
379 }
380
381 uprobe = container_of(rule, struct lttng_event_rule_uprobe,
382 parent);
383 name_copy = strdup(name);
384 if (!name_copy) {
385 status = LTTNG_EVENT_RULE_STATUS_ERROR;
386 goto end;
387 }
388
389 if (uprobe->name) {
390 free(uprobe->name);
391 }
392
393 uprobe->name = name_copy;
394 name_copy = NULL;
395end:
396 return status;
397}
398
399enum lttng_event_rule_status lttng_event_rule_uprobe_get_name(
400 const struct lttng_event_rule *rule, const char **name)
401{
402 struct lttng_event_rule_uprobe *uprobe;
403 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
404
405 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !name) {
406 status = LTTNG_EVENT_RULE_STATUS_INVALID;
407 goto end;
408 }
409
410 uprobe = container_of(rule, struct lttng_event_rule_uprobe,
411 parent);
412 if (!uprobe->name) {
413 status = LTTNG_EVENT_RULE_STATUS_UNSET;
414 goto end;
415 }
416
417 *name = uprobe->name;
418end:
419 return status;
420}
This page took 0.044379 seconds and 5 git commands to generate.