X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=3216e5002efb950f00055ffa0f3b4e6f56f0ac6d;hp=3f1ab9fdc4bb8f17abe91345355b11f3263d61e2;hb=2463b7879c00298daa79744cdaae82ac061a4ed8;hpb=3a4595c2469472dee1656cde5f8882c2123efd3c diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 3f1ab9fdc..3216e5002 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,6 @@ #include #include -#include #include #include "lttng-ctl-helper.h" @@ -2956,6 +2956,13 @@ int lttng_register_trigger(struct lttng_trigger *trigger) 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); @@ -2965,11 +2972,39 @@ int lttng_register_trigger(struct lttng_trigger *trigger) 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; @@ -2990,6 +3025,39 @@ int lttng_register_trigger(struct lttng_trigger *trigger) 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( @@ -3003,20 +3071,45 @@ int lttng_register_trigger(struct lttng_trigger *trigger) } } + { + 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); @@ -3026,7 +3119,36 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger) 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; } @@ -3046,7 +3168,7 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger) */ 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; @@ -3074,11 +3196,58 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger) 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. */