The session daemon uses triggers internally. For instance, the trigger
and notification subsystem is used to implement the automatic rotation
of sessions based on a size threshold.
Currently, a user of the C API will see those internal triggers if it is
running as the same user as the session daemon. This can be unexpected
by user code that assumes it will be alone in creating triggers.
Moreover, it is possible for external users to unregister those triggers
which would cause bugs.
As the triggers gain more capabilities, it is likely that the session
daemon will keep using them to implement features internally. Thus,
an internal "is_hidden" property is introduced in lttng_trigger.
A "hidden" trigger is a trigger that is not returned by the listings.
It is used to hide triggers that are used internally by the session
daemon so that they can't be listed nor unregistered by external
clients.
This is a property that can only be set internally by the session
daemon. As such, it is not serialized nor set by a
"create_from_buffer" constructor.
The hidden property is preserved by copies.
Note that notifications originating from an "hidden" trigger will not
be sent to clients that are not within the session daemon's process.
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I61b7949075172fcd428289e2eb670d03c19bdf71
+ /*
+ * A "hidden" trigger is a trigger that is not externally listed.
+ * It is used to hide triggers that are used internally by the session
+ * daemon so that they can't be listed nor unregistered by external
+ * clients.
+ *
+ * This is a property that can only be set internally by the session
+ * daemon. As such, it is not serialized nor set by a
+ * "create_from_buffer" constructor.
+ *
+ * The hidden property is preserved by copies.
+ *
+ * Note that notifications originating from an "hidden" trigger will not
+ * be sent to clients that are not within the session daemon's process.
+ */
+ bool is_hidden;
+
/*
* The lock is used to protect against concurrent trigger execution and
* trigger removal.
/*
* The lock is used to protect against concurrent trigger execution and
* trigger removal.
bool lttng_trigger_is_equal(
const struct lttng_trigger *a, const struct lttng_trigger *b);
bool lttng_trigger_is_equal(
const struct lttng_trigger *a, const struct lttng_trigger *b);
+LTTNG_HIDDEN
+bool lttng_trigger_is_hidden(const struct lttng_trigger *trigger);
+
+LTTNG_HIDDEN
+void lttng_trigger_set_hidden(struct lttng_trigger *trigger);
+
LTTNG_HIDDEN
void lttng_trigger_get(struct lttng_trigger *trigger);
LTTNG_HIDDEN
void lttng_trigger_get(struct lttng_trigger *trigger);
int lttng_triggers_add(
struct lttng_triggers *triggers, struct lttng_trigger *trigger);
int lttng_triggers_add(
struct lttng_triggers *triggers, struct lttng_trigger *trigger);
+/*
+ * Remove all triggers marked as hidden from the provided trigger set.
+ */
+LTTNG_HIDDEN
+int lttng_triggers_remove_hidden_triggers(struct lttng_triggers *triggers);
+
/*
* Serialize a trigger set to an lttng_payload object.
* Return LTTNG_OK on success, negative lttng error code on error.
/*
* Serialize a trigger set to an lttng_payload object.
* Return LTTNG_OK on success, negative lttng error code on error.
struct notification_thread_handle *notification_thread,
struct lttng_triggers **return_triggers)
{
struct notification_thread_handle *notification_thread,
struct lttng_triggers **return_triggers)
{
enum lttng_error_code ret_code;
struct lttng_triggers *triggers = NULL;
enum lttng_error_code ret_code;
struct lttng_triggers *triggers = NULL;
+ ret = lttng_triggers_remove_hidden_triggers(triggers);
+ if (ret) {
+ ret_code = LTTNG_ERR_UNK;
+ goto end;
+ }
+
*return_triggers = triggers;
triggers = NULL;
ret_code = LTTNG_OK;
*return_triggers = triggers;
triggers = NULL;
ret_code = LTTNG_OK;
&client->communication.inbound.creds);
client->gid = LTTNG_SOCK_GET_GID_CRED(
&client->communication.inbound.creds);
&client->communication.inbound.creds);
client->gid = LTTNG_SOCK_GET_GID_CRED(
&client->communication.inbound.creds);
- DBG("Received handshake from client (uid = %u, gid = %u) with version %i.%i",
+ client->is_sessiond = LTTNG_SOCK_GET_PID_CRED(&client->communication.inbound.creds) == getpid();
+ DBG("Received handshake from client: uid = %u, gid = %u, protocol version = %i.%i, client is sessiond = %s",
client->uid, client->gid, (int) client->major,
client->uid, client->gid, (int) client->major,
+ (int) client->minor,
+ client->is_sessiond ? "true" : "false");
if (handshake_client->major !=
LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
if (handshake_client->major !=
LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
+ if (lttng_trigger_is_hidden(trigger) && !client->is_sessiond) {
+ /*
+ * Notifications resulting from an hidden trigger are
+ * only sent to the session daemon.
+ */
+ continue;
+ }
+
if (source_object_creds) {
if (client->uid != lttng_credentials_get_uid(source_object_creds) &&
client->gid != lttng_credentials_get_gid(source_object_creds) &&
if (source_object_creds) {
if (client->uid != lttng_credentials_get_uid(source_object_creds) &&
client->gid != lttng_credentials_get_gid(source_object_creds) &&
uint8_t major, minor;
uid_t uid;
gid_t gid;
uint8_t major, minor;
uid_t uid;
gid_t gid;
/*
* Indicates if the credentials and versions of the client have been
* checked.
/*
* Indicates if the credentials and versions of the client have been
* checked.
+ /* Ensure this trigger is not visible to external users. */
+ lttng_trigger_set_hidden(session->rotate_trigger);
lttng_trigger_set_credentials(
session->rotate_trigger, &session_creds);
lttng_trigger_set_credentials(
session->rotate_trigger, &session_creds);
+ if (a->is_hidden != b->is_hidden) {
+ return false;
+ }
+
+LTTNG_HIDDEN
+bool lttng_trigger_is_hidden(const struct lttng_trigger *trigger)
+{
+ return trigger->is_hidden;
+}
+
+LTTNG_HIDDEN
+void lttng_trigger_set_hidden(struct lttng_trigger *trigger)
+{
+ assert(!trigger->is_hidden);
+ trigger->is_hidden = true;
+}
+
LTTNG_HIDDEN
enum lttng_trigger_status lttng_trigger_set_name(struct lttng_trigger *trigger,
const char* name)
LTTNG_HIDDEN
enum lttng_trigger_status lttng_trigger_set_name(struct lttng_trigger *trigger,
const char* name)
+LTTNG_HIDDEN
+int lttng_triggers_remove_hidden_triggers(struct lttng_triggers *triggers)
+{
+ int ret;
+ unsigned int trigger_count, i = 0;
+ enum lttng_trigger_status trigger_status;
+
+ assert(triggers);
+
+ trigger_status = lttng_triggers_get_count(triggers, &trigger_count);
+ assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
+
+ while (i < trigger_count) {
+ const struct lttng_trigger *trigger =
+ lttng_triggers_get_at_index(triggers, i);
+
+ if (lttng_trigger_is_hidden(trigger)) {
+ ret = lttng_dynamic_pointer_array_remove_pointer(
+ &triggers->array, i);
+ if (ret) {
+ goto end;
+ }
+
+ trigger_count--;
+ } else {
+ i++;
+ }
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
const struct lttng_trigger *lttng_triggers_get_at_index(
const struct lttng_triggers *triggers, unsigned int index)
{
const struct lttng_trigger *lttng_triggers_get_at_index(
const struct lttng_triggers *triggers, unsigned int index)
{
copy->tracer_token = trigger->tracer_token;
copy->registered = trigger->registered;
copy->tracer_token = trigger->tracer_token;
copy->registered = trigger->registered;
+ copy->is_hidden = trigger->is_hidden;
goto end;
error_cleanup_trigger:
goto end;
error_cleanup_trigger: