2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <lttng/trigger/trigger-internal.h>
9 #include <lttng/condition/condition-internal.h>
10 #include <lttng/action/action-internal.h>
11 #include <common/credentials.h>
12 #include <common/payload.h>
13 #include <common/payload-view.h>
14 #include <common/error.h>
15 #include <common/optional.h>
19 bool lttng_trigger_validate(struct lttng_trigger
*trigger
)
28 if (!trigger
->creds
.uid
.is_set
) {
33 valid
= lttng_condition_validate(trigger
->condition
) &&
34 lttng_action_validate(trigger
->action
);
39 struct lttng_trigger
*lttng_trigger_create(
40 struct lttng_condition
*condition
,
41 struct lttng_action
*action
)
43 struct lttng_trigger
*trigger
= NULL
;
45 if (!condition
|| !action
) {
49 trigger
= zmalloc(sizeof(struct lttng_trigger
));
54 urcu_ref_init(&trigger
->ref
);
56 lttng_condition_get(condition
);
57 trigger
->condition
= condition
;
59 lttng_action_get(action
);
60 trigger
->action
= action
;
67 * Note: the lack of reference counting 'get' on the condition object is normal.
68 * This API was exposed as such in 2.11. The client is not expected to call
69 * lttng_condition_destroy on the returned object.
71 struct lttng_condition
*lttng_trigger_get_condition(
72 struct lttng_trigger
*trigger
)
74 return trigger
? trigger
->condition
: NULL
;
78 const struct lttng_condition
*lttng_trigger_get_const_condition(
79 const struct lttng_trigger
*trigger
)
81 return trigger
->condition
;
86 * Note: the lack of reference counting 'get' on the action object is normal.
87 * This API was exposed as such in 2.11. The client is not expected to call
88 * lttng_action_destroy on the returned object.
90 struct lttng_action
*lttng_trigger_get_action(
91 struct lttng_trigger
*trigger
)
93 return trigger
? trigger
->action
: NULL
;
97 const struct lttng_action
*lttng_trigger_get_const_action(
98 const struct lttng_trigger
*trigger
)
100 return trigger
->action
;
103 static void trigger_destroy_ref(struct urcu_ref
*ref
)
105 struct lttng_trigger
*trigger
=
106 container_of(ref
, struct lttng_trigger
, ref
);
107 struct lttng_action
*action
= lttng_trigger_get_action(trigger
);
108 struct lttng_condition
*condition
=
109 lttng_trigger_get_condition(trigger
);
114 /* Release ownership. */
115 lttng_action_put(action
);
116 lttng_condition_put(condition
);
121 void lttng_trigger_destroy(struct lttng_trigger
*trigger
)
123 lttng_trigger_put(trigger
);
127 ssize_t
lttng_trigger_create_from_payload(
128 struct lttng_payload_view
*src_view
,
129 struct lttng_trigger
**trigger
)
131 ssize_t ret
, offset
= 0, condition_size
, action_size
;
132 struct lttng_condition
*condition
= NULL
;
133 struct lttng_action
*action
= NULL
;
134 const struct lttng_trigger_comm
*trigger_comm
;
135 struct lttng_credentials creds
= {
136 .uid
= LTTNG_OPTIONAL_INIT_UNSET
,
137 .gid
= LTTNG_OPTIONAL_INIT_UNSET
,
140 if (!src_view
|| !trigger
) {
145 /* lttng_trigger_comm header */
146 trigger_comm
= (typeof(trigger_comm
)) src_view
->buffer
.data
;
148 /* Set the trigger's creds. */
149 if (trigger_comm
->uid
> (uint64_t) ((uid_t
) -1)) {
150 /* UID out of range for this platform. */
155 LTTNG_OPTIONAL_SET(&creds
.uid
, trigger_comm
->uid
);
157 offset
+= sizeof(*trigger_comm
);
159 /* struct lttng_condition */
160 struct lttng_payload_view condition_view
=
161 lttng_payload_view_from_view(
162 src_view
, offset
, -1);
164 condition_size
= lttng_condition_create_from_payload(&condition_view
,
168 if (condition_size
< 0) {
169 ret
= condition_size
;
173 offset
+= condition_size
;
175 /* struct lttng_action */
176 struct lttng_payload_view action_view
=
177 lttng_payload_view_from_view(
178 src_view
, offset
, -1);
180 action_size
= lttng_action_create_from_payload(&action_view
, &action
);
183 if (action_size
< 0) {
187 offset
+= action_size
;
189 /* Unexpected size of inner-elements; the buffer is corrupted. */
190 if ((ssize_t
) trigger_comm
->length
!= condition_size
+ action_size
) {
195 *trigger
= lttng_trigger_create(condition
, action
);
201 lttng_trigger_set_credentials(*trigger
, &creds
);
204 * The trigger object owns references to the action and condition
207 lttng_condition_put(condition
);
210 lttng_action_put(action
);
216 lttng_condition_destroy(condition
);
217 lttng_action_destroy(action
);
223 * Both elements are stored contiguously, see their "*_comm" structure
224 * for the detailed format.
227 int lttng_trigger_serialize(struct lttng_trigger
*trigger
,
228 struct lttng_payload
*payload
)
231 size_t header_offset
, size_before_payload
;
232 struct lttng_trigger_comm trigger_comm
= {};
233 struct lttng_trigger_comm
*header
;
234 const struct lttng_credentials
*creds
= NULL
;
236 creds
= lttng_trigger_get_credentials(trigger
);
239 trigger_comm
.uid
= LTTNG_OPTIONAL_GET(creds
->uid
);
241 header_offset
= payload
->buffer
.size
;
242 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &trigger_comm
,
243 sizeof(trigger_comm
));
248 size_before_payload
= payload
->buffer
.size
;
249 ret
= lttng_condition_serialize(trigger
->condition
, payload
);
254 ret
= lttng_action_serialize(trigger
->action
, payload
);
259 /* Update payload size. */
260 header
= (typeof(header
)) (payload
->buffer
.data
+ header_offset
);
261 header
->length
= payload
->buffer
.size
- size_before_payload
;
267 bool lttng_trigger_is_equal(
268 const struct lttng_trigger
*a
, const struct lttng_trigger
*b
)
271 * Name is not taken into account since it is cosmetic only.
273 if (!lttng_condition_is_equal(a
->condition
, b
->condition
)) {
277 if (!lttng_action_is_equal(a
->action
, b
->action
)) {
281 if (!lttng_credentials_is_equal(lttng_trigger_get_credentials(a
),
282 lttng_trigger_get_credentials(b
))) {
290 void lttng_trigger_get(struct lttng_trigger
*trigger
)
292 urcu_ref_get(&trigger
->ref
);
296 void lttng_trigger_put(struct lttng_trigger
*trigger
)
302 urcu_ref_put(&trigger
->ref
, trigger_destroy_ref
);
306 const struct lttng_credentials
*lttng_trigger_get_credentials(
307 const struct lttng_trigger
*trigger
)
309 return &trigger
->creds
;
313 void lttng_trigger_set_credentials(struct lttng_trigger
*trigger
,
314 const struct lttng_credentials
*creds
)
317 trigger
->creds
= *creds
;
320 enum lttng_trigger_status
lttng_trigger_set_owner_uid(
321 struct lttng_trigger
*trigger
, uid_t uid
)
323 enum lttng_trigger_status ret
= LTTNG_TRIGGER_STATUS_OK
;
324 const struct lttng_credentials creds
= {
325 .uid
= LTTNG_OPTIONAL_INIT_VALUE(uid
),
326 .gid
= LTTNG_OPTIONAL_INIT_UNSET
,
330 ret
= LTTNG_TRIGGER_STATUS_INVALID
;
334 /* Client-side validation only to report a clearer error. */
335 if (geteuid() != 0) {
336 ret
= LTTNG_TRIGGER_STATUS_PERMISSION_DENIED
;
340 lttng_trigger_set_credentials(trigger
, &creds
);
346 enum lttng_trigger_status
lttng_trigger_get_owner_uid(
347 const struct lttng_trigger
*trigger
, uid_t
*uid
)
349 enum lttng_trigger_status ret
= LTTNG_TRIGGER_STATUS_OK
;
350 const struct lttng_credentials
*creds
= NULL
;
352 if (!trigger
|| !uid
) {
353 ret
= LTTNG_TRIGGER_STATUS_INVALID
;
357 if (!trigger
->creds
.uid
.is_set
) {
358 ret
= LTTNG_TRIGGER_STATUS_UNSET
;
362 creds
= lttng_trigger_get_credentials(trigger
);
363 *uid
= lttng_credentials_get_uid(creds
);