#include <string.h>
#include <unistd.h>
+#include <common/bytecode/bytecode.h>
#include <common/common.h>
#include <common/compat/string.h>
#include <common/defaults.h>
#include <common/filter/filter-ast.h>
#include <common/filter/filter-parser.h>
-#include <common/filter/filter-bytecode.h>
#include <common/filter/memstream.h>
#include "lttng-ctl-helper.h"
struct lttcomm_session_msg *message_lsm;
struct lttng_payload message;
struct lttng_payload reply;
+ struct lttng_trigger *reply_trigger = NULL;
+ enum lttng_domain_type domain_type;
+ struct lttng_credentials creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+ .gid = LTTNG_OPTIONAL_INIT_UNSET,
+ };
+
lttng_payload_init(&message);
lttng_payload_init(&reply);
goto end;
}
+ if (!trigger->creds.uid.is_set) {
+ /* Use the client credentials as the trigger credentials */
+ lttng_trigger_set_credentials(trigger, &creds);
+ } else {
+ /*
+ * Validate that either the current trigger credentials and the
+ * client credentials are identical or that the current user is
+ * root. The root user can register, unregister triggers for
+ * himself and other users.
+ * This check is also present on the sessiond side, using the
+ * credentials passed on the socket. These check are all
+ * "safety" checks.
+ */
+ const struct lttng_credentials *trigger_creds =
+ lttng_trigger_get_credentials(trigger);
+ if (!lttng_credentials_is_equal_uid(trigger_creds, &creds)) {
+ if (lttng_credentials_get_uid(&creds) != 0) {
+ ret = -LTTNG_ERR_EPERM;
+ goto end;
+ }
+ }
+ }
+
if (!lttng_trigger_validate(trigger)) {
ret = -LTTNG_ERR_INVALID_TRIGGER;
goto end;
}
+ domain_type = lttng_trigger_get_underlying_domain_type_restriction(
+ trigger);
+
+ lsm.domain.type = domain_type;
+
ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
if (ret) {
ret = -LTTNG_ERR_NOMEM;
message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
+ if (getenv("LTTNG_REGISTER_TRIGGER_DRY_RUN")) {
+ /*
+ * Don't really send the request, just deserialize, validate
+ * that it is equal to the original trigger (to test
+ * serialization and deserialization), and return.
+ */
+ ssize_t sz;
+
+ struct lttng_payload_view pv = lttng_payload_view_from_payload(
+ &message, sizeof(lsm), -1);
+ sz = lttng_trigger_create_from_payload(&pv, &reply_trigger);
+ if (sz != pv.buffer.size - sizeof(lsm)) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ if (!reply_trigger) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ if (!lttng_trigger_is_equal(trigger, reply_trigger)) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ /* Give it a dummy name. */
+ lttng_trigger_set_name(trigger, "yop");
+
+ ret = 0;
+ goto end;
+ }
+
{
struct lttng_payload_view message_view =
lttng_payload_view_from_payload(
}
}
+ {
+ struct lttng_payload_view reply_view =
+ lttng_payload_view_from_payload(
+ &reply, 0, reply.buffer.size);
+
+ ret = lttng_trigger_create_from_payload(
+ &reply_view, &reply_trigger);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
+ }
+
+ ret = lttng_trigger_assign_name(trigger, reply_trigger);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
+
ret = 0;
end:
lttng_payload_reset(&message);
lttng_payload_reset(&reply);
+ lttng_trigger_destroy(reply_trigger);
return ret;
}
-int lttng_unregister_trigger(struct lttng_trigger *trigger)
+int lttng_unregister_trigger(const struct lttng_trigger *trigger)
{
int ret;
struct lttcomm_session_msg lsm;
struct lttcomm_session_msg *message_lsm;
struct lttng_payload message;
struct lttng_payload reply;
+ struct lttng_trigger *copy = NULL;
+ struct lttng_credentials creds = {
+ .uid = LTTNG_OPTIONAL_INIT_VALUE(geteuid()),
+ .gid = LTTNG_OPTIONAL_INIT_UNSET,
+ };
lttng_payload_init(&message);
lttng_payload_init(&reply);
goto end;
}
- if (!lttng_trigger_validate(trigger)) {
+ copy = lttng_trigger_copy(trigger);
+ if (!copy) {
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ if (!copy->creds.uid.is_set) {
+ /* Use the client credentials as the trigger credentials */
+ lttng_trigger_set_credentials(copy, &creds);
+ } else {
+ /*
+ * Validate that either the current trigger credentials and the
+ * client credentials are identical or that the current user is
+ * root. The root user can register, unregister triggers for
+ * himself and other users.
+ * This check is also present on the sessiond side, using the
+ * credentials passed on the socket. These check are all
+ * "safety" checks.
+ */
+ const struct lttng_credentials *trigger_creds =
+ lttng_trigger_get_credentials(copy);
+ if (!lttng_credentials_is_equal_uid(trigger_creds, &creds)) {
+ if (lttng_credentials_get_uid(&creds) != 0) {
+ ret = -LTTNG_ERR_EPERM;
+ goto end;
+ }
+ }
+ }
+
+ if (!lttng_trigger_validate(copy)) {
ret = -LTTNG_ERR_INVALID_TRIGGER;
goto end;
}
*/
message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
- ret = lttng_trigger_serialize(trigger, &message);
+ ret = lttng_trigger_serialize(copy, &message);
if (ret < 0) {
ret = -LTTNG_ERR_UNK;
goto end;
ret = 0;
end:
+ lttng_trigger_destroy(copy);
lttng_payload_reset(&message);
lttng_payload_reset(&reply);
return ret;
}
+/*
+ * Ask the session daemon for all registered triggers.
+ * Allocate a lttng_triggers collection.
+ * On error, returns a negative value.
+ */
+enum lttng_error_code lttng_list_triggers(struct lttng_triggers **triggers)
+{
+ int ret;
+ struct lttcomm_session_msg lsm;
+ struct lttng_payload_view lsm_view =
+ lttng_payload_view_init_from_buffer(
+ (const char *) &lsm, 0, sizeof(lsm));
+ struct lttng_triggers *local_triggers = NULL;
+ struct lttng_payload reply;
+
+ lttng_payload_init(&reply);
+
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_LIST_TRIGGERS;
+
+ ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &reply);
+ if (ret < 0) {
+ goto end;
+ }
+
+ {
+ struct lttng_payload_view reply_view =
+ lttng_payload_view_from_payload(
+ &reply, 0, reply.buffer.size);
+ ret = lttng_triggers_create_from_payload(
+ &reply_view, &local_triggers);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
+ }
+
+ *triggers = local_triggers;
+ local_triggers = NULL;
+ ret = LTTNG_OK;
+end:
+ lttng_payload_reset(&reply);
+ lttng_triggers_destroy(local_triggers);
+ return ret;
+}
+
/*
* lib constructor.
*/