From 159b042f34366d0fde5dcd73b4231c558922a664 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Tue, 17 Mar 2020 16:14:30 -0400 Subject: [PATCH] Refactor: lttng-ctl: follow terminology of the tracker documentation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This commit harmonizes the process attribute tracker API and serialization formats (save/restore and MI) with the documentation with regards to the terminology used. The message of the parent commit adjusting the manual pages of the lttng-track and lttng-untrack commands details those terminology changes and their rationale. Some problems with the API introduced during the 2.12 development cycle are also adressed: Type safety: - The process attribute tracker is made type safe with regards to the platform's native types to express process attributes. Where the original API casted all integral values to integers, this change introduces accessors for all process attribute types (pid_t, uid_t, gid_t). This makes it easier to use the API safely and without producing warnings in user's code. Another benefit of adopting this explicit type-safe approach is that is will make it easier to add new attributes which are not expressible (or non-ambiguously expressible) using `int` and `string` types (e.g. tracking a virtual PID within a given namespace). Ambiguity of INCLUDE_ALL, EXCLUDE_ALL, and INCLUDE_SET states: - The original tracker API has a notion of 'enabled' pid_tracker which is confusing to users: - enable = 0: everything is tracked, - enable = 1: a list of tracked pids is provided, which may be empty. - pid '-1' is *special* and tracks or untracks everything. This was replaced with a 'special' opaque value meaning 'ALL' which, while being clearer, was still confusing and hard to document. The revised API explicitly expresses the notion of a tracking policy (`enum lttng_tracking_policy`). When that policy is set to `LTTNG_TRACKING_POLICY_INCLUDE_SET`, the inclusion set can be queried and/or mutated. On top of being clearer, this aligns more closely with the internal lttng-sessiond daemon API which gets rid of a lot of code to handle those special cases. The resulting code is more verbose, but a lot easier to understand. Moreover, the types introduced (e.g. lttng_process_attr_values) are meant to be re-used if a new `LTTNG_TRACKING_POLICY_EXCLUDE_SET` tracking policy is added in the future. Documentation: - The revised API includes a complete documentation. It documents the API usage, but also adds implementation notes such explicitly mentionning when/where user names and group names are resolved. Client: - While making the changes to use this new API, some error messages are clarified (or added). The resulting output when listing the trackers was also changed to be more compact. The CLI output now also makes use of the terminology used in the documentation for all commands interacting with process attribute trackers. It is now also possible to specify multiple process attribute trackers along with the --all option for the lttng-track and lttng-untrack command. For instance: `lttng tracker --userspace --vpid --vuid --all` is now allowed. The same process attribute tracker can also be specified more than once in a command, as follows: `lttng track --userspace --vpid 43,11 --vpid 55,77` Since the serialization had been changed during the 2.12 cycle, I changed them further to use the API's terminology in the element names. Signed-off-by: Jérémie Galarneau Change-Id: I5f0ea2849eb024ea6944b2ee7dbadfd893cc0be4 --- include/Makefile.am | 1 - include/lttng/lttng-error.h | 10 +- include/lttng/tracker-internal.h | 73 -- include/lttng/tracker.h | 653 ++++++++-- src/bin/lttng-sessiond/client.c | 335 ++--- src/bin/lttng-sessiond/cmd.c | 364 +++--- src/bin/lttng-sessiond/cmd.h | 39 +- src/bin/lttng-sessiond/kernel.c | 498 +++++--- src/bin/lttng-sessiond/kernel.h | 23 +- src/bin/lttng-sessiond/save.c | 301 +++-- src/bin/lttng-sessiond/trace-kernel.c | 48 +- src/bin/lttng-sessiond/trace-kernel.h | 12 +- src/bin/lttng-sessiond/trace-ust.c | 460 ++++--- src/bin/lttng-sessiond/trace-ust.h | 73 +- src/bin/lttng-sessiond/tracker.c | 639 ++++------ src/bin/lttng-sessiond/tracker.h | 66 +- src/bin/lttng-sessiond/ust-app.c | 9 +- src/bin/lttng/commands/list.c | 359 ++++-- src/bin/lttng/commands/track-untrack.c | 1097 ++++++++--------- src/common/Makefile.am | 2 +- src/common/config/config-session-abi.h | 34 +- src/common/config/session-config.c | 310 +++-- src/common/config/session.xsd | 103 +- src/common/error.c | 6 +- src/common/kernel-ctl/kernel-ctl.c | 29 +- src/common/kernel-ctl/kernel-ctl.h | 6 +- src/common/macros.h | 2 + src/common/mi-lttng-4.0.xsd | 140 +-- src/common/mi-lttng.c | 261 ++-- src/common/mi-lttng.h | 46 +- src/common/sessiond-comm/sessiond-comm.h | 133 +- src/common/tracker.c | 681 ++++++---- src/common/tracker.h | 91 ++ src/common/utils.c | 135 ++ src/common/utils.h | 10 +- src/lib/lttng-ctl/Makefile.am | 3 +- src/lib/lttng-ctl/deprecated-symbols.c | 5 + src/lib/lttng-ctl/lttng-ctl-helper.h | 8 +- src/lib/lttng-ctl/lttng-ctl.c | 309 +---- src/lib/lttng-ctl/tracker.c | 757 ++++++++++++ tests/regression/tools/mi/test_mi | 6 +- .../tools/save-load/load-42-trackers.lttng | 54 +- tests/regression/tools/save-load/test_load | 6 +- 43 files changed, 4830 insertions(+), 3367 deletions(-) delete mode 100644 include/lttng/tracker-internal.h create mode 100644 src/common/tracker.h create mode 100644 src/lib/lttng-ctl/tracker.c diff --git a/include/Makefile.am b/include/Makefile.am index ccd0d87d6..1f89b1bf6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -161,6 +161,5 @@ noinst_HEADERS = \ lttng/userspace-probe-internal.h \ lttng/session-internal.h \ lttng/session-descriptor-internal.h \ - lttng/tracker-internal.h \ version.h \ version.i diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h index 4757d3d60..38fe7837c 100644 --- a/include/lttng/lttng-error.h +++ b/include/lttng/lttng-error.h @@ -124,8 +124,8 @@ enum lttng_error_code { LTTNG_ERR_EXCLUSION_NOMEM = 111, /* Lack of memory while processing event exclusions */ LTTNG_ERR_INVALID_EVENT_NAME = 112, /* Invalid event name */ LTTNG_ERR_INVALID_CHANNEL_NAME = 113, /* Invalid channel name */ - LTTNG_ERR_ID_TRACKED = 114, /* ID already tracked */ - LTTNG_ERR_ID_NOT_TRACKED = 115, /* ID not tracked */ + LTTNG_ERR_PROCESS_ATTR_EXISTS = 114, /* Process attribute is already tracked */ + LTTNG_ERR_PROCESS_ATTR_MISSING = 115, /* Process attribute was not tracked */ LTTNG_ERR_INVALID_CHANNEL_DOMAIN = 116, /* Invalid channel domain */ LTTNG_ERR_OVERFLOW = 117, /* Overflow occurred. */ LTTNG_ERR_SESSION_NOT_STARTED = 118, /* Session not started */ @@ -172,13 +172,15 @@ enum lttng_error_code { LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR = 159, /* Session was already cleared since it became inactive. */ LTTNG_ERR_USER_NOT_FOUND = 160, /* User not found. */ LTTNG_ERR_GROUP_NOT_FOUND = 161, /* Group not found. */ + LTTNG_ERR_UNSUPPORTED_DOMAIN = 162, /* Unsupported domain used. */ + LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY = 163, /* Operation does not apply to the process attribute tracker's tracking policy */ /* MUST be last element of the manually-assigned section of the enum */ LTTNG_ERR_NR, /* Backward-compatibility assignments */ - LTTNG_ERR_PID_TRACKED = LTTNG_ERR_ID_TRACKED, /* Backward compat alias to LTTNG_ERR_ID_TRACKED */ - LTTNG_ERR_PID_NOT_TRACKED = LTTNG_ERR_ID_NOT_TRACKED, /* Backward compat alias to LTTNG_ERR_ID_NOT_TRACKED */ + LTTNG_ERR_PID_TRACKED = LTTNG_ERR_PROCESS_ATTR_EXISTS, /* Backward compat alias */ + LTTNG_ERR_PID_NOT_TRACKED = LTTNG_ERR_PROCESS_ATTR_MISSING, /* Backward compat alias */ }; /* diff --git a/include/lttng/tracker-internal.h b/include/lttng/tracker-internal.h deleted file mode 100644 index daa6d80b1..000000000 --- a/include/lttng/tracker-internal.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2019 Jonathan Rajotte - * - * SPDX-License-Identifier: LGPL-2.1-only - * - */ - -#ifndef LTTNG_TRACKER_INTERNAL_H -#define LTTNG_TRACKER_INTERNAL_H - -#include -#include -#include -#include -#include - -struct lttng_tracker_id { - enum lttng_tracker_id_type type; - int value; - char *string; -}; - -struct lttng_tracker_ids { - struct lttng_tracker_id *id_array; - unsigned int count; -}; - -LTTNG_HIDDEN -bool lttng_tracker_id_is_equal(const struct lttng_tracker_id *left, - const struct lttng_tracker_id *right); - -/* - * A copy acts like memcpy. It does not allocate new memory. - */ -LTTNG_HIDDEN -int lttng_tracker_id_copy(struct lttng_tracker_id *dest, - const struct lttng_tracker_id *src); - -/* - * Duplicate an lttng_tracker_id. - * The returned object must be freed via lttng_tracker_id_destroy. - */ -LTTNG_HIDDEN -struct lttng_tracker_id *lttng_tracker_id_duplicate( - const struct lttng_tracker_id *src); - -/* - * Allocate a new list of lttng_tracker_id. - * The returned object must be freed via lttng_tracker_ids_destroy. - */ -LTTNG_HIDDEN -struct lttng_tracker_ids *lttng_tracker_ids_create(unsigned int base_count); - -/* - * Return the non-const pointer of an element at index "index" of a - * lttng_tracker_ids. - * - * The ownership of the lttng_tracker_id element is NOT transfered. - * The returned object can NOT be freed via lttng_tracker_id_destroy. - */ -LTTNG_HIDDEN -struct lttng_tracker_id *lttng_tracker_ids_get_pointer_of_index( - const struct lttng_tracker_ids *list, unsigned int index); - -/* - * Serialize a ids collection to a lttng_dynamic_buffer. - * Return LTTNG_OK on success, negative lttng error code on error. - */ -LTTNG_HIDDEN -int lttng_tracker_ids_serialize(const struct lttng_tracker_ids *ids, - struct lttng_dynamic_buffer *buffer); - -#endif /* LTTNG_TRACKER_INTERNAL_H */ diff --git a/include/lttng/tracker.h b/include/lttng/tracker.h index 4f813eeb9..fa91abab6 100644 --- a/include/lttng/tracker.h +++ b/include/lttng/tracker.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2019 Jonathan Rajotte + * Copyright (C) 2020 Jérémie Galarneau * * SPDX-License-Identifier: LGPL-2.1-only * @@ -9,191 +10,581 @@ #define LTTNG_TRACKER_H #include +#include +#include #include +#include + #ifdef __cplusplus extern "C" { #endif -enum lttng_tracker_type { - LTTNG_TRACKER_PID = 0, - LTTNG_TRACKER_VPID = 1, - LTTNG_TRACKER_UID = 2, - LTTNG_TRACKER_GID = 3, - LTTNG_TRACKER_VUID = 4, - LTTNG_TRACKER_VGID = 5, +/* + * Process attribute tracked by a tracker. + */ +enum lttng_process_attr { + /* Kernel space domain only. */ + LTTNG_PROCESS_ATTR_PROCESS_ID = 0, + /* Kernel and user space domains. */ + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID = 1, + /* Kernel space domain only. */ + LTTNG_PROCESS_ATTR_USER_ID = 2, + /* Kernel and user space domains. */ + LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID = 3, + /* Kernel space domain only. */ + LTTNG_PROCESS_ATTR_GROUP_ID = 4, + /* Kernel and user space domains. */ + LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID = 5, +}; + +/* + * Tracking (filtering) policy of a process attribute tracker. + */ +enum lttng_tracking_policy { + /* + * Track all possible process attribute value of a given type + * (i.e. no filtering). + * This is the default state of a process attribute tracker. + */ + LTTNG_TRACKING_POLICY_INCLUDE_ALL = 0, + /* Exclude all possible process attribute values of a given type. */ + LTTNG_TRACKING_POLICY_EXCLUDE_ALL = 1, + /* Track a set of specific process attribute values. */ + LTTNG_TRACKING_POLICY_INCLUDE_SET = 2, +}; + +/* + * Type of a process attribute value. + * + * This allows the use of the matching accessor given the type of a value. + */ +enum lttng_process_attr_value_type { + LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID = -1, + LTTNG_PROCESS_ATTR_VALUE_TYPE_PID = 0, + LTTNG_PROCESS_ATTR_VALUE_TYPE_UID = 1, + LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME = 2, + LTTNG_PROCESS_ATTR_VALUE_TYPE_GID = 3, + LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME = 4, }; -enum lttng_tracker_id_type { - LTTNG_ID_UNKNOWN = -1, - LTTNG_ID_ALL = 0, - LTTNG_ID_VALUE = 1, - LTTNG_ID_STRING = 2, +enum lttng_process_attr_tracker_handle_status { + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND = -7, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND = -6, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY = -5, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST = -4, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR = -3, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR = -2, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID = -1, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK = 0, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS = 1, + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING = 2, }; -enum lttng_tracker_id_status { - /* Invalid tracker id parameter. */ - LTTNG_TRACKER_ID_STATUS_INVALID = -1, - LTTNG_TRACKER_ID_STATUS_OK = 0, - /* Tracker id parameter is unset. */ - LTTNG_TRACKER_ID_STATUS_UNSET = 1, +enum lttng_process_attr_values_status { + LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE = -2, + LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID = -1, + LTTNG_PROCESS_ATTR_VALUES_STATUS_OK = 0, }; /* - * A tracker id. + * A process attribute tracker handle. + * + * A process attribute tracker is an _inclusion set_ of process + * attribute values. Tracked processes are allowed to emit events, + * provided those events are targeted by enabled event rules. + * + * An LTTng session is created with a number of process attribute + * trackers by default. The process attributes that can be tracked vary by + * domain (see enum lttng_process_attr). + * + * Trackers are per-domain (user and kernel space) and allow the filtering + * of events based on a process's attributes. */ -struct lttng_tracker_id; +struct lttng_process_attr_tracker_handle; + +/* A set of process attribute values. */ +struct lttng_process_attr_values; /* - * A collection of tracker id. + * Get a handle to one of the process attribute trackers of a session's domain. + * + * Returns LTTNG_OK and a process attribute tracker handle on success, + * or an lttng_error_code on error. + * + * The tracker's ownership is transfered to the caller. Use + * lttng_process_attr_tracker_handle_destroy() to dispose of it. + */ +extern enum lttng_error_code lttng_session_get_tracker_handle( + const char *session_name, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + struct lttng_process_attr_tracker_handle **out_tracker_handle); + +/* + * Destroy a process attribute tracker handle. */ -struct lttng_tracker_ids; +extern void lttng_process_attr_tracker_handle_destroy( + struct lttng_process_attr_tracker_handle *tracker_handle); /* - * Create a tracker id for the passed tracker type. - * Users must set the tracker id using the matching API call. + * Get the tracking policy of a process attribute tracker. * - * On success, the caller is responsible for calling lttng_tracker_id_destroy. - * On error, return NULL. + * Returns the LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK and the tracking + * policy of a process attribute tracker on success, + * LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID on error. */ -extern struct lttng_tracker_id *lttng_tracker_id_create(void); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_tracker_handle_get_tracking_policy( + const struct lttng_process_attr_tracker_handle *tracker_handle, + enum lttng_tracking_policy *policy); /* - * Configure the tracker id using the numerical representation of the resource - * to be tracked/untracked. + * Set the tracking policy of a process attribute tracker. * - * If the tracker id was already configured, calling this function will replace - * the previous configuration and free memory as necessary. + * Setting the tracking policy to the current tracking policy has no effect. * - * Returns LTTNG_TRACKER_ID_STATUS_OK on success, - * LTTNG_TRACKER_ID_STATUS_INVALID is the passed parameter is invalid. + * Returns the LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID on error. */ -extern enum lttng_tracker_id_status lttng_tracker_id_set_value( - struct lttng_tracker_id *id, int value); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_tracker_handle_set_tracking_policy( + const struct lttng_process_attr_tracker_handle *tracker_handle, + enum lttng_tracking_policy policy); /* - * Configure the tracker id using the string representation of the resource to - * be tracked/untracked. + * Add a numerical PID to the process ID process attribute tracker inclusion + * set. * - * If the tracker id was already configured, calling this function will replace - * the previous configuration and free memory as necessary. + * Returns LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_process_id_tracker_handle_add_pid( + const struct lttng_process_attr_tracker_handle + *process_id_tracker, + pid_t pid); + +/* + * Remove a numerical PID from the process ID process attribute tracker include + * set. * - * Returns LTTNG_TRACKER_ID_STATUS_OK on success, - * LTTNG_TRACKER_ID_STATUS_INVALID if the passed parameter is invalid. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. */ -extern enum lttng_tracker_id_status lttng_tracker_id_set_string( - struct lttng_tracker_id *id, const char *value); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_process_id_tracker_handle_remove_pid( + const struct lttng_process_attr_tracker_handle + *process_id_tracker, + pid_t pid); /* - * Configure the tracker id to track/untrack all resources for the tracker type. + * Add a numerical PID to the virtual process ID process attribute tracker + * inclusion set. * - * If the tracker id was already configured, calling this function will replace - * the previous configuration and free memory as necessary. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_process_id_tracker_handle_add_pid( + const struct lttng_process_attr_tracker_handle + *process_id_tracker, + pid_t vpid); + +/* + * Remove a numerical PID from the virtual process ID process attribute tracker + * inclusion set. * - * Returns LTTNG_TRACKER_ID_STATUS_OK on success, - * LTTNG_TRACKER_ID_STATUS_INVALID if the passed parameter is invalid. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. */ -extern enum lttng_tracker_id_status lttng_tracker_id_set_all( - struct lttng_tracker_id *id); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_process_id_tracker_handle_remove_pid( + const struct lttng_process_attr_tracker_handle + *process_id_tracker, + pid_t vpid); /* - * Destroy a tracker id. + * Add a numerical UID to the user ID process attribute tracker inclusion set. + * + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. */ -extern void lttng_tracker_id_destroy(struct lttng_tracker_id *id); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_user_id_tracker_handle_add_uid( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + uid_t uid); /* - * Get the type of a tracker id. + * Remove a numerical UID from the user ID process attribute tracker include + * set. + * + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. */ -extern enum lttng_tracker_id_type lttng_tracker_id_get_type( - const struct lttng_tracker_id *id); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_user_id_tracker_handle_remove_uid( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + uid_t uid); /* - * Get the value of a tracker id. + * Add a user name to the user ID process attribute tracker inclusion set. + * + * The user name resolution is performed by the session daemon on addition to + * the user ID inclusion set. * - * Returns LTTNG_TRACKER_ID_OK on success, - * LTTNG_TRACKER_ID_STATUS_INVALID when the tracker is not of type - * LTTNG_ID_VALUE, - * LTTNG_TRACKER_ID_STATUS_UNSET when the tracker is not set. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. */ -extern enum lttng_tracker_id_status lttng_tracker_id_get_value( - const struct lttng_tracker_id *id, int *value); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_user_id_tracker_handle_add_user_name( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + const char *user_name); /* - * Get the string representation of the tracker id. + * Remove a user name from the user ID process attribute tracker include + * set. + * + * No name resolution is performed; the user name will be matched against the + * names in the inclusion set. * - * Returns LTTNG_TRACKER_ID_OK on success, - * LTTNG_TRACKER_ID_STATUS_INVALID when the tracker is not of type - * LTTNG_ID_STRING, - * LTTNG_TRACKER_ID_STATUS_UNSET when the tracker is not set. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. */ -extern enum lttng_tracker_id_status lttng_tracker_id_get_string( - const struct lttng_tracker_id *id, const char **value); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_user_id_tracker_handle_remove_user_name( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + const char *user_name); /* - * Add ID to session tracker. + * Add a numerical UID to the virtual user ID process attribute tracker + * inclusion set. * - * tracker_type is the type of tracker. - * id is the lttng_tracker_type to track. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_user_id_tracker_handle_add_uid( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + uid_t vuid); + +/* + * Remove a numerical UID from the virtual user ID process attribute tracker + * inclusion set. * - * Returns 0 on success else a negative LTTng error code. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. */ -extern int lttng_track_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_user_id_tracker_handle_remove_uid( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + uid_t vuid); /* - * Remove ID from session tracker. + * Add a user name to the virtual user ID process attribute tracker include + * set. + * + * The user name resolution is performed by the session daemon on addition to + * the virtual user ID inclusion set. * - * tracker_type is the type of tracker. - * id is the lttng_tracker_type to untrack. - * Returns 0 on success else a negative LTTng error code. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. */ -extern int lttng_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_user_id_tracker_handle_add_user_name( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + const char *virtual_user_name); /* - * List IDs of a tracker. + * Remove a user name from the virtual user ID process attribute tracker + * inclusion set. * - * On success, ids is allocated. - * The ids collection must be freed by the caller with lttng_destroy_ids(). + * No name resolution is performed; the user name will be matched against the + * names in the inclusion set. * - * Returns 0 on success, else a negative LTTng error code. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. */ -extern int lttng_list_tracker_ids(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - struct lttng_tracker_ids **ids); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_user_id_tracker_handle_remove_user_name( + const struct lttng_process_attr_tracker_handle *user_id_tracker, + const char *virtual_user_name); /* - * Backward compatibility. - * Add PID to session tracker. + * Add a numerical GID to the group ID process attribute tracker inclusion set. * - * A pid argument >= 0 adds the PID to the session tracker. - * A pid argument of -1 means "track all PIDs". + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_group_id_tracker_handle_add_gid( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + gid_t gid); + +/* + * Remove a numerical GID from the group ID process attribute tracker include + * set. * - * Returns 0 on success else a negative LTTng error code. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. */ -extern int lttng_track_pid(struct lttng_handle *handle, int pid); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_group_id_tracker_handle_remove_gid( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + gid_t gid); /* - * Backward compatibility. - * Remove PID from session tracker. + * Add a group name to the group ID process attribute tracker inclusion set. * - * A pid argument >= 0 removes the PID from the session tracker. - * A pid argument of -1 means "untrack all PIDs". + * The group name resolution is performed by the session daemon on addition to + * the group ID inclusion set. * - * Returns 0 on success else a negative LTTng error code. + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. */ -extern int lttng_untrack_pid(struct lttng_handle *handle, int pid); +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_group_id_tracker_handle_add_group_name( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + const char *group_name); + +/* + * Remove a group name from the group ID process attribute tracker include + * set. + * + * No name resolution is performed; the user name will be matched against the + * names in the inclusion set. + * + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_group_id_tracker_handle_remove_group_name( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + const char *group_name); + +/* + * Add a numerical GID to the virtual group ID process attribute tracker + * inclusion set. + * + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_group_id_tracker_handle_add_gid( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + gid_t vgid); + +/* + * Remove a numerical GID from the virtual group ID process attribute tracker + * inclusion set. + * + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_group_id_tracker_handle_remove_gid( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + gid_t vgid); + +/* + * Add a group name to the virtual group ID process attribute tracker include + * set. + * + * The group name resolution is performed by the session daemon on addition to + * the virtual group ID inclusion set. + * + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_EXISTS if it was already + * present in the inclusion set, and + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if an invalid tracker + * argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_group_id_tracker_handle_add_group_name( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + const char *virtual_group_name); + +/* + * Remove a group name from the virtual group ID process attribute tracker + * inclusion set. + * + * No name resolution is performed; the user name will be matched against the + * names in the inclusion set. + * + * Returns LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_MISSING if it was not present + * in the inclusion set, and LTTNG_PROCESS_ATTR_TRACKED_HANDLE_STATUS_INVALID if + * an invalid tracker argument was provided. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_virtual_group_id_tracker_handle_remove_group_name( + const struct lttng_process_attr_tracker_handle *group_id_tracker, + const char *virtual_group_name); + +/* + * Get the process attribute values that are part of a tracker's inclusion set. + * + * The values returned are a snapshot of the values that are part of the + * tracker's inclusion set at the moment of the invocation; it is not updated + * as entries are added or removed. + * + * The values remain valid until the tracker is destroyed. + * + * Returns LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID if the tracker's policy is + * not LTTNG_POLICY_INCLUDE_SET. + */ +extern enum lttng_process_attr_tracker_handle_status +lttng_process_attr_tracker_handle_get_inclusion_set( + struct lttng_process_attr_tracker_handle *tracker_handle, + const struct lttng_process_attr_values **values); /* - * Backward compatibility - * List PIDs in the tracker. + * Get the count of values within a set of process attribute values. * - * enabled is set to whether the PID tracker is enabled. - * pids is set to an allocated array of PIDs currently tracked. On - * success, pids must be freed by the caller. - * nr_pids is set to the number of entries contained by the pids array. + * Returns LTTNG_PROCESS_ATTR_VALUES_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID if an invalid argument is provided. + */ +extern enum lttng_process_attr_values_status +lttng_process_attr_values_get_count( + const struct lttng_process_attr_values *values, + unsigned int *count); + +/* + * Get the type of a process attribute value at a given index. + * + * Returns a process attribute value type on success, + * LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID if an invalid argument is provided. + */ +extern enum lttng_process_attr_value_type +lttng_process_attr_values_get_type_at_index( + const struct lttng_process_attr_values *values, + unsigned int index); + +/* + * Get a process ID process attribute value. + * + * Returns LTTNG_PROCESS_ATTR_VALUES_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value + * is not a process ID. + */ +extern enum lttng_process_attr_values_status +lttng_process_attr_values_get_pid_at_index( + const struct lttng_process_attr_values *values, + unsigned int index, + pid_t *pid); + +/* + * Get a user ID process attribute value. + * + * Returns LTTNG_PROCESS_ATTR_VALUES_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value + * is not a user ID. + */ +extern enum lttng_process_attr_values_status +lttng_process_attr_values_get_uid_at_index( + const struct lttng_process_attr_values *values, + unsigned int index, + uid_t *uid); + +/* + * Get a user name process attribute value. + * + * Returns LTTNG_PROCESS_ATTR_VALUES_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value + * is not a user name. + */ +extern enum lttng_process_attr_values_status +lttng_process_attr_values_get_user_name_at_index( + const struct lttng_process_attr_values *values, + unsigned int index, + const char **user_name); + +/* + * Get a group ID process attribute value. + * + * Returns LTTNG_PROCESS_ATTR_VALUES_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value + * is not a group ID. + */ +extern enum lttng_process_attr_values_status +lttng_process_attr_values_get_gid_at_index( + const struct lttng_process_attr_values *values, + unsigned int index, + gid_t *gid); + +/* + * Get a group name process attribute value. + * + * Returns LTTNG_PROCESS_ATTR_VALUES_STATUS_OK on success, + * LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE if the process attribute value + * is not a group name. + */ +extern enum lttng_process_attr_values_status +lttng_process_attr_values_get_group_name_at_index( + const struct lttng_process_attr_values *values, + unsigned int index, + const char **group_name); + +/* The following entry points are deprecated. */ + +/* + * Deprecated: see `lttng_process_attr_tracker_handle_get_inclusion_set` and + * `lttng_process_tracker_handle_get_tracking_policy`. + * + * List tracked PIDs. + * + * `enabled` indicates whether or not the PID tracker is enabled. + * + * `pids` is set to an allocated array of PIDs currently being tracked. On + * success, `pids` must be freed by the caller. + * + * `nr_pids` is set to the number of entries contained in the `pids` array. * * Returns 0 on success, else a negative LTTng error code. */ @@ -203,30 +594,42 @@ extern int lttng_list_tracker_pids(struct lttng_handle *handle, size_t *nr_pids); /* - * Get a tracker id from the list at a given index. + * Deprecated: see `lttng_process_attr_process_id_tracker_handle_add_pid`. + * + * Add PID to session tracker. * - * Note that the list maintains the ownership of the returned tracker id. - * It must not be destroyed by the user, nor should it be held beyond the - * lifetime of the tracker id list. + * A pid argument >= 0 adds the PID to the session's PID tracker. + * A pid argument of -1 means "track all PIDs". * - * Returns a tracker id, or NULL on error. - */ -extern const struct lttng_tracker_id *lttng_tracker_ids_get_at_index( - const struct lttng_tracker_ids *ids, unsigned int index); - -/* - * Get the number of tracker id in a tracker id list. + * Note on 'real' PIDs vs 'virtual' VPIDs: + * - With the user space domain specified, this function will add a VPID + * value to the virtual process ID process attribute tracker's inclusion + * set. + * - With the kernel space domain specified, this function will add a PID + * value to the process ID process attribute tracker's inclusion set. * - * Return LTTNG_TRACKER_ID_STATUS on sucess, - * LTTNG_TRACKER_ID_STATUS_INVALID when passed invalid parameters. + * Returns 0 on success, else a negative LTTng error code. */ -extern enum lttng_tracker_id_status lttng_tracker_ids_get_count( - const struct lttng_tracker_ids *ids, unsigned int *count); +extern int lttng_track_pid(struct lttng_handle *handle, int pid); /* - * Destroy a tracker id list. + * Deprecated: see `lttng_process_attr_process_id_tracker_handle_remove_pid`. + * + * Remove PID from session tracker. + * + * A pid argument >= 0 removes the PID from the session's PID tracker. + * A pid argument of -1 means "untrack all PIDs". + * + * Note on 'real' PIDs vs 'virtual' VPIDs: + * - With the user space domain specified, this function will remove a VPID + * value from the virtual process ID process attribute tracker's inclusion + * set. + * - With the kernel space domain specified, this function will remove a PID + * value from the process ID process attribute tracker's inclusion set. + * + * Returns 0 on success, else a negative LTTng error code. */ -extern void lttng_tracker_ids_destroy(struct lttng_tracker_ids *ids); +extern int lttng_untrack_pid(struct lttng_handle *handle, int pid); #ifdef __cplusplus } diff --git a/src/bin/lttng-sessiond/client.c b/src/bin/lttng-sessiond/client.c index 473491f37..a36b81c18 100644 --- a/src/bin/lttng-sessiond/client.c +++ b/src/bin/lttng-sessiond/client.c @@ -7,18 +7,23 @@ * */ -#include -#include -#include -#include +#include "common/buffer-view.h" +#include "common/dynamic-buffer.h" +#include "common/sessiond-comm/sessiond-comm.h" +#include "lttng/lttng-error.h" +#include "lttng/tracker.h" #include +#include #include #include -#include #include -#include #include -#include +#include +#include +#include +#include +#include +#include #include "client.h" #include "lttng-sessiond.h" @@ -780,11 +785,12 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, case LTTNG_LIST_CHANNELS: case LTTNG_LIST_EVENTS: case LTTNG_LIST_SYSCALLS: - case LTTNG_LIST_TRACKER_IDS: + case LTTNG_SESSION_LIST_ROTATION_SCHEDULES: + case LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY: + case LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET: case LTTNG_DATA_PENDING: case LTTNG_ROTATE_SESSION: case LTTNG_ROTATION_GET_INFO: - case LTTNG_SESSION_LIST_ROTATION_SCHEDULES: break; default: /* Setup lttng message with no payload */ @@ -1196,141 +1202,189 @@ error_add_context: kernel_poll_pipe[1]); break; } - case LTTNG_TRACK_ID: + case LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE: + case LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE: { - struct lttng_tracker_id *id = NULL; - enum lttng_tracker_id_status status; - - id = lttng_tracker_id_create(); - if (!id) { - ret = LTTNG_ERR_NOMEM; + struct lttng_dynamic_buffer payload; + struct lttng_buffer_view payload_view; + const bool add_value = + cmd_ctx->lsm->cmd_type == + LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE; + const size_t name_len = + cmd_ctx->lsm->u.process_attr_tracker_add_remove_include_value + .name_len; + const enum lttng_domain_type domain_type = + (enum lttng_domain_type) + cmd_ctx->lsm->domain.type; + const enum lttng_process_attr process_attr = + (enum lttng_process_attr) cmd_ctx->lsm->u + .process_attr_tracker_add_remove_include_value + .process_attr; + const enum lttng_process_attr_value_type value_type = + (enum lttng_process_attr_value_type) cmd_ctx + ->lsm->u + .process_attr_tracker_add_remove_include_value + .value_type; + struct process_attr_value *value; + enum lttng_error_code ret_code; + + /* Receive remaining variable length payload if applicable. */ + if (name_len > LOGIN_NAME_MAX) { + /* + * POSIX mandates user and group names that are at least + * 8 characters long. Note that although shadow-utils + * (useradd, groupaadd, etc.) use 32 chars as their + * limit (from bits/utmp.h, UT_NAMESIZE), + * LOGIN_NAME_MAX is defined to 256. + */ + ERR("Rejecting process attribute tracker value %s as the provided exceeds the maximal allowed length: argument length = %zu, maximal length = %d", + add_value ? "addition" : "removal", + name_len, LOGIN_NAME_MAX); + ret = LTTNG_ERR_INVALID; goto error; } - switch (cmd_ctx->lsm->u.id_tracker.id_type) { - case LTTNG_ID_ALL: - status = lttng_tracker_id_set_all(id); - break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_set_value( - id, cmd_ctx->lsm->u.id_tracker.u.value); - break; - case LTTNG_ID_STRING: - { - const size_t var_len = cmd_ctx->lsm->u.id_tracker.u.var_len; - char *string = NULL; - - string = zmalloc(var_len); - if (!string) { - lttng_tracker_id_destroy(id); + lttng_dynamic_buffer_init(&payload); + if (name_len != 0) { + /* + * Receive variable payload for user/group name + * arguments. + */ + ret = lttng_dynamic_buffer_set_size(&payload, name_len); + if (ret) { + ERR("Failed to allocate buffer to receive payload of %s process attribute tracker value argument", + add_value ? "add" : "remove"); ret = LTTNG_ERR_NOMEM; - goto error; + goto error_add_remove_tracker_value; } - DBG("Receiving var len tracker id string from client"); - ret = lttcomm_recv_unix_sock(*sock, string, var_len); + + ret = lttcomm_recv_unix_sock( + *sock, payload.data, name_len); if (ret <= 0) { - DBG("Nothing received"); + ERR("Failed to receive payload of %s process attribute tracker value argument", + add_value ? "add" : "remove"); *sock_error = 1; - free(string); - lttng_tracker_id_destroy(id); - ret = LTTNG_ERR_INVALID; - goto error; - } - if (strnlen(string, var_len) != var_len - 1) { - DBG("String received as tracker ID is not NULL-terminated"); - free(string); - lttng_tracker_id_destroy(id); - ret = LTTNG_ERR_INVALID; - goto error; + ret = LTTNG_ERR_INVALID_PROTOCOL; + goto error_add_remove_tracker_value; } + } - status = lttng_tracker_id_set_string(id, string); - free(string); - break; + payload_view = lttng_buffer_view_from_dynamic_buffer( + &payload, 0, name_len); + /* + * Validate the value type and domains are legal for the process + * attribute tracker that is specified and convert the value to + * add/remove to the internal sessiond representation. + */ + ret_code = process_attr_value_from_comm(domain_type, + process_attr, value_type, + &cmd_ctx->lsm->u.process_attr_tracker_add_remove_include_value + .integral_value, + &payload_view, &value); + if (ret_code != LTTNG_OK) { + ret = ret_code; + goto error_add_remove_tracker_value; + } + + if (add_value) { + ret = cmd_process_attr_tracker_inclusion_set_add_value( + cmd_ctx->session, domain_type, + process_attr, value); + } else { + ret = cmd_process_attr_tracker_inclusion_set_remove_value( + cmd_ctx->session, domain_type, + process_attr, value); } - default: - lttng_tracker_id_destroy(id); - ret = LTTNG_ERR_INVALID; + process_attr_value_destroy(value); + error_add_remove_tracker_value: + lttng_dynamic_buffer_reset(&payload); + break; + } + case LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY: + { + enum lttng_tracking_policy tracking_policy; + const enum lttng_domain_type domain_type = + (enum lttng_domain_type) + cmd_ctx->lsm->domain.type; + const enum lttng_process_attr process_attr = + (enum lttng_process_attr) cmd_ctx->lsm->u + .process_attr_tracker_get_tracking_policy + .process_attr; + + ret = cmd_process_attr_tracker_get_tracking_policy( + cmd_ctx->session, domain_type, process_attr, + &tracking_policy); + if (ret != LTTNG_OK) { goto error; } - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ERR("Invalid value for tracker id"); - ret = LTTNG_ERR_INVALID; - lttng_tracker_id_destroy(id); + ret = setup_lttng_msg_no_cmd_header(cmd_ctx, + &(uint32_t){tracking_policy}, sizeof(uint32_t)); + if (ret < 0) { + ret = LTTNG_ERR_NOMEM; goto error; } - - ret = cmd_track_id(cmd_ctx->session, - cmd_ctx->lsm->u.id_tracker.tracker_type, - cmd_ctx->lsm->domain.type, id); - lttng_tracker_id_destroy(id); + ret = LTTNG_OK; break; } - case LTTNG_UNTRACK_ID: + case LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY: { - struct lttng_tracker_id *id = NULL; - enum lttng_tracker_id_status status; - - id = lttng_tracker_id_create(); - - switch (cmd_ctx->lsm->u.id_tracker.id_type) { - case LTTNG_ID_ALL: - status = lttng_tracker_id_set_all(id); - break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_set_value( - id, cmd_ctx->lsm->u.id_tracker.u.value); - break; - case LTTNG_ID_STRING: - { - const size_t var_len = cmd_ctx->lsm->u.id_tracker.u.var_len; - char *string = NULL; - - string = zmalloc(var_len); - if (!string) { - ret = LTTNG_ERR_NOMEM; - lttng_tracker_id_destroy(id); - goto error; - } - DBG("Receiving var len tracker id string from client"); - ret = lttcomm_recv_unix_sock(*sock, string, var_len); - if (ret <= 0) { - DBG("Nothing received"); - *sock_error = 1; - lttng_tracker_id_destroy(id); - free(string); - ret = LTTNG_ERR_INVALID; - goto error; - } - if (strnlen(string, var_len) != var_len - 1) { - DBG("String received as tracker ID is not NULL-terminated"); - lttng_tracker_id_destroy(id); - free(string); - ret = LTTNG_ERR_INVALID; - goto error; - } - status = lttng_tracker_id_set_string(id, string); - free(string); - break; + const enum lttng_tracking_policy tracking_policy = + (enum lttng_tracking_policy) cmd_ctx->lsm->u + .process_attr_tracker_set_tracking_policy + .tracking_policy; + const enum lttng_domain_type domain_type = + (enum lttng_domain_type) + cmd_ctx->lsm->domain.type; + const enum lttng_process_attr process_attr = + (enum lttng_process_attr) cmd_ctx->lsm->u + .process_attr_tracker_set_tracking_policy + .process_attr; + + ret = cmd_process_attr_tracker_set_tracking_policy( + cmd_ctx->session, domain_type, process_attr, + tracking_policy); + if (ret != LTTNG_OK) { + goto error; } - default: - lttng_tracker_id_destroy(id); - ret = LTTNG_ERR_INVALID; + break; + } + case LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET: + { + struct lttng_process_attr_values *values; + struct lttng_dynamic_buffer reply; + const enum lttng_domain_type domain_type = + (enum lttng_domain_type) + cmd_ctx->lsm->domain.type; + const enum lttng_process_attr process_attr = + (enum lttng_process_attr) cmd_ctx->lsm->u + .process_attr_tracker_get_inclusion_set + .process_attr; + + ret = cmd_process_attr_tracker_get_inclusion_set( + cmd_ctx->session, domain_type, process_attr, + &values); + if (ret != LTTNG_OK) { goto error; } - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ERR("Invalid tracker id"); - lttng_tracker_id_destroy(id); - ret = LTTNG_ERR_INVALID; - goto error; + lttng_dynamic_buffer_init(&reply); + ret = lttng_process_attr_values_serialize(values, &reply); + if (ret < 0) { + goto error_tracker_get_inclusion_set; } - ret = cmd_untrack_id(cmd_ctx->session, - cmd_ctx->lsm->u.id_tracker.tracker_type, - cmd_ctx->lsm->domain.type, id); - lttng_tracker_id_destroy(id); + ret = setup_lttng_msg_no_cmd_header( + cmd_ctx, reply.data, reply.size); + if (ret < 0) { + ret = LTTNG_ERR_NOMEM; + goto error_tracker_get_inclusion_set; + } + ret = LTTNG_OK; + + error_tracker_get_inclusion_set: + lttng_process_attr_values_destroy(values); + lttng_dynamic_buffer_reset(&reply); break; } case LTTNG_ENABLE_EVENT: @@ -1556,49 +1610,6 @@ error_add_context: ret = LTTNG_OK; break; } - case LTTNG_LIST_TRACKER_IDS: - { - struct lttcomm_tracker_command_header cmd_header; - struct lttng_tracker_ids *ids = NULL; - enum lttng_tracker_id_status status; - unsigned int nr_ids; - struct lttng_dynamic_buffer buf; - - ret = cmd_list_tracker_ids( - cmd_ctx->lsm->u.id_tracker.tracker_type, - cmd_ctx->session, cmd_ctx->lsm->domain.type, - &ids); - if (ret != LTTNG_OK) { - goto error; - } - - lttng_dynamic_buffer_init(&buf); - - status = lttng_tracker_ids_get_count(ids, &nr_ids); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_INVALID; - goto error_list_tracker; - } - - cmd_header.nb_tracker_id = nr_ids; - - ret = lttng_tracker_ids_serialize(ids, &buf); - if (ret < 0) { - goto error_list_tracker; - } - - ret = setup_lttng_msg(cmd_ctx, buf.data, buf.size, &cmd_header, - sizeof(cmd_header)); - error_list_tracker: - lttng_tracker_ids_destroy(ids); - lttng_dynamic_buffer_reset(&buf); - if (ret < 0) { - goto error; - } - - ret = LTTNG_OK; - break; - } case LTTNG_SET_CONSUMER_URI: { size_t nb_uri, len; diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 5e522d6fe..2bd010f89 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -6,6 +6,9 @@ * */ +#include "bin/lttng-sessiond/tracker.h" +#include "lttng/lttng-error.h" +#include "lttng/tracker.h" #define _LGPL_SOURCE #include #include @@ -1431,112 +1434,6 @@ error: return ret; } -/* - * Command LTTNG_TRACK_ID processed by the client thread. - * - * Called with session lock held. - */ -int cmd_track_id(struct ltt_session *session, - enum lttng_tracker_type tracker_type, - enum lttng_domain_type domain, - const struct lttng_tracker_id *id) -{ - int ret; - - rcu_read_lock(); - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct ltt_kernel_session *ksess; - - ksess = session->kernel_session; - - ret = kernel_track_id(tracker_type, ksess, id); - if (ret != LTTNG_OK) { - goto error; - } - - kernel_wait_quiescent(); - break; - } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess; - - usess = session->ust_session; - - ret = trace_ust_track_id(tracker_type, usess, id); - if (ret != LTTNG_OK) { - goto error; - } - break; - } - default: - ret = LTTNG_ERR_UNKNOWN_DOMAIN; - goto error; - } - - ret = LTTNG_OK; - -error: - rcu_read_unlock(); - return ret; -} - -/* - * Command LTTNG_UNTRACK_ID processed by the client thread. - * - * Called with session lock held. - */ -int cmd_untrack_id(struct ltt_session *session, - enum lttng_tracker_type tracker_type, - enum lttng_domain_type domain, - const struct lttng_tracker_id *id) -{ - int ret; - - rcu_read_lock(); - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct ltt_kernel_session *ksess; - - ksess = session->kernel_session; - - ret = kernel_untrack_id(tracker_type, ksess, id); - if (ret != LTTNG_OK) { - goto error; - } - - kernel_wait_quiescent(); - break; - } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess; - - usess = session->ust_session; - - ret = trace_ust_untrack_id(tracker_type, usess, id); - if (ret != LTTNG_OK) { - goto error; - } - break; - } - default: - ret = LTTNG_ERR_UNKNOWN_DOMAIN; - goto error; - } - - ret = LTTNG_OK; - -error: - rcu_read_unlock(); - return ret; -} - /* * Command LTTNG_ENABLE_CHANNEL processed by the client thread. * @@ -1708,6 +1605,211 @@ end: return ret; } +enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy *policy) +{ + enum lttng_error_code ret_code = LTTNG_OK; + const struct process_attr_tracker *tracker; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (!session->kernel_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + tracker = kernel_get_process_attr_tracker( + session->kernel_session, process_attr); + break; + case LTTNG_DOMAIN_UST: + if (!session->ust_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + tracker = trace_ust_get_process_attr_tracker( + session->ust_session, process_attr); + break; + default: + ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN; + goto end; + } + if (tracker) { + *policy = process_attr_tracker_get_tracking_policy(tracker); + } else { + ret_code = LTTNG_ERR_INVALID; + } +end: + return ret_code; +} + +enum lttng_error_code cmd_process_attr_tracker_set_tracking_policy( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy) +{ + enum lttng_error_code ret_code = LTTNG_OK; + + switch (policy) { + case LTTNG_TRACKING_POLICY_INCLUDE_SET: + case LTTNG_TRACKING_POLICY_EXCLUDE_ALL: + case LTTNG_TRACKING_POLICY_INCLUDE_ALL: + break; + default: + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (!session->kernel_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + ret_code = kernel_process_attr_tracker_set_tracking_policy( + session->kernel_session, process_attr, policy); + break; + case LTTNG_DOMAIN_UST: + if (!session->ust_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + ret_code = trace_ust_process_attr_tracker_set_tracking_policy( + session->ust_session, process_attr, policy); + break; + default: + ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN; + break; + } +end: + return ret_code; +} + +enum lttng_error_code cmd_process_attr_tracker_inclusion_set_add_value( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + const struct process_attr_value *value) +{ + enum lttng_error_code ret_code = LTTNG_OK; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (!session->kernel_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + ret_code = kernel_process_attr_tracker_inclusion_set_add_value( + session->kernel_session, process_attr, value); + break; + case LTTNG_DOMAIN_UST: + if (!session->ust_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + ret_code = trace_ust_process_attr_tracker_inclusion_set_add_value( + session->ust_session, process_attr, value); + break; + default: + ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN; + break; + } +end: + return ret_code; +} + +enum lttng_error_code cmd_process_attr_tracker_inclusion_set_remove_value( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + const struct process_attr_value *value) +{ + enum lttng_error_code ret_code = LTTNG_OK; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (!session->kernel_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + ret_code = kernel_process_attr_tracker_inclusion_set_remove_value( + session->kernel_session, process_attr, value); + break; + case LTTNG_DOMAIN_UST: + if (!session->ust_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + ret_code = trace_ust_process_attr_tracker_inclusion_set_remove_value( + session->ust_session, process_attr, value); + break; + default: + ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN; + break; + } +end: + return ret_code; +} + +enum lttng_error_code cmd_process_attr_tracker_get_inclusion_set( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + struct lttng_process_attr_values **values) +{ + enum lttng_error_code ret_code = LTTNG_OK; + const struct process_attr_tracker *tracker; + enum process_attr_tracker_status status; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (!session->kernel_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + tracker = kernel_get_process_attr_tracker( + session->kernel_session, process_attr); + break; + case LTTNG_DOMAIN_UST: + if (!session->ust_session) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + tracker = trace_ust_get_process_attr_tracker( + session->ust_session, process_attr); + break; + default: + ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN; + goto end; + } + + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + status = process_attr_tracker_get_inclusion_set(tracker, values); + switch (status) { + case PROCESS_ATTR_TRACKER_STATUS_OK: + ret_code = LTTNG_OK; + break; + case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY: + ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY; + break; + case PROCESS_ATTR_TRACKER_STATUS_ERROR: + ret_code = LTTNG_ERR_NOMEM; + break; + default: + ret_code = LTTNG_ERR_UNK; + break; + } + +end: + return ret_code; +} + /* * Command LTTNG_DISABLE_EVENT processed by the client thread. */ @@ -2566,56 +2668,6 @@ ssize_t cmd_list_syscalls(struct lttng_event **events) return syscall_table_list(events); } -/* - * Command LTTNG_LIST_TRACKER_IDS processed by the client thread. - * - * Called with session lock held. - */ -int cmd_list_tracker_ids(enum lttng_tracker_type tracker_type, - struct ltt_session *session, - enum lttng_domain_type domain, - struct lttng_tracker_ids **ids) -{ - int ret = LTTNG_OK; - - switch (domain) { - case LTTNG_DOMAIN_KERNEL: - { - struct ltt_kernel_session *ksess; - - ksess = session->kernel_session; - ret = kernel_list_tracker_ids(tracker_type, ksess, ids); - if (ret != LTTNG_OK) { - ret = -LTTNG_ERR_KERN_LIST_FAIL; - goto error; - } - break; - } - case LTTNG_DOMAIN_UST: - { - struct ltt_ust_session *usess; - - usess = session->ust_session; - ret = trace_ust_list_tracker_ids(tracker_type, usess, ids); - if (ret != LTTNG_OK) { - ret = -LTTNG_ERR_UST_LIST_FAIL; - goto error; - } - break; - } - case LTTNG_DOMAIN_LOG4J: - case LTTNG_DOMAIN_JUL: - case LTTNG_DOMAIN_PYTHON: - default: - ret = -LTTNG_ERR_UND; - goto error; - } - -error: - /* Return negative value to differentiate return code */ - return ret; -} - /* * Command LTTNG_START_TRACE processed by the client thread. * diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 23d9d5e02..1be746031 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -9,8 +9,10 @@ #define CMD_H #include "context.h" -#include "session.h" #include "lttng-sessiond.h" +#include "lttng/tracker.h" +#include "session.h" +#include struct notification_thread_handle; @@ -47,14 +49,33 @@ int cmd_disable_channel(struct ltt_session *session, int cmd_enable_channel(struct ltt_session *session, const struct lttng_domain *domain, const struct lttng_channel *attr, int wpipe); -int cmd_track_id(struct ltt_session *session, - enum lttng_tracker_type tracker_type, + +/* Process attribute tracker commands */ +enum lttng_error_code cmd_process_attr_tracker_get_tracking_policy( + struct ltt_session *session, enum lttng_domain_type domain, - const struct lttng_tracker_id *id); -int cmd_untrack_id(struct ltt_session *session, - enum lttng_tracker_type tracker_type, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy *policy); +enum lttng_error_code cmd_process_attr_tracker_set_tracking_policy( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy); +enum lttng_error_code cmd_process_attr_tracker_inclusion_set_add_value( + struct ltt_session *session, enum lttng_domain_type domain, - const struct lttng_tracker_id *id); + enum lttng_process_attr process_attr, + const struct process_attr_value *value); +enum lttng_error_code cmd_process_attr_tracker_inclusion_set_remove_value( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + const struct process_attr_value *value); +enum lttng_error_code cmd_process_attr_tracker_get_inclusion_set( + struct ltt_session *session, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + struct lttng_process_attr_values **values); /* Event commands */ int cmd_disable_event(struct ltt_session *session, @@ -104,10 +125,6 @@ ssize_t cmd_list_tracepoints(enum lttng_domain_type domain, ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, struct lttng_snapshot_output **outputs); ssize_t cmd_list_syscalls(struct lttng_event **events); -int cmd_list_tracker_ids(enum lttng_tracker_type tracker_type, - struct ltt_session *session, - enum lttng_domain_type domain, - struct lttng_tracker_ids **ids); int cmd_data_pending(struct ltt_session *session); diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 4ee4bea64..547d2ec6c 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -5,6 +5,11 @@ * */ +#include "bin/lttng-sessiond/tracker.h" +#include "common/tracker.h" +#include "common/utils.h" +#include "lttng/lttng-error.h" +#include "lttng/tracker.h" #define _LGPL_SOURCE #include #include @@ -669,281 +674,370 @@ error: return ret; } -static struct lttng_tracker_list *get_id_tracker_list( +static +struct process_attr_tracker *_kernel_get_process_attr_tracker( struct ltt_kernel_session *session, - enum lttng_tracker_type tracker_type) + enum lttng_process_attr process_attr) { - switch (tracker_type) { - case LTTNG_TRACKER_PID: - return session->tracker_list_pid; - case LTTNG_TRACKER_VPID: - return session->tracker_list_vpid; - case LTTNG_TRACKER_UID: - return session->tracker_list_uid; - case LTTNG_TRACKER_VUID: - return session->tracker_list_vuid; - case LTTNG_TRACKER_GID: - return session->tracker_list_gid; - case LTTNG_TRACKER_VGID: - return session->tracker_list_vgid; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + return session->tracker_pid; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + return session->tracker_vpid; + case LTTNG_PROCESS_ATTR_USER_ID: + return session->tracker_uid; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + return session->tracker_vuid; + case LTTNG_PROCESS_ATTR_GROUP_ID: + return session->tracker_gid; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + return session->tracker_vgid; default: return NULL; } } -int kernel_track_id(enum lttng_tracker_type tracker_type, +const struct process_attr_tracker *kernel_get_process_attr_tracker( struct ltt_kernel_session *session, - const struct lttng_tracker_id *id) + enum lttng_process_attr process_attr) { - int ret, value; - struct lttng_tracker_list *tracker_list; - struct lttng_tracker_ids *saved_ids; + return (const struct process_attr_tracker *) + _kernel_get_process_attr_tracker(session, process_attr); +} - ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); - if (ret != LTTNG_OK) { - return ret; - } +enum lttng_error_code kernel_process_attr_tracker_set_tracking_policy( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy) +{ + int ret; + enum lttng_error_code ret_code = LTTNG_OK; + struct process_attr_tracker *tracker = + _kernel_get_process_attr_tracker(session, process_attr); + enum lttng_tracking_policy previous_policy; - tracker_list = get_id_tracker_list(session, tracker_type); - if (!tracker_list) { - return LTTNG_ERR_INVALID; + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + goto end; } - /* Save list for restore on error. */ - ret = lttng_tracker_id_get_list(tracker_list, &saved_ids); - if (ret != LTTNG_OK) { - return LTTNG_ERR_INVALID; + previous_policy = process_attr_tracker_get_tracking_policy(tracker); + ret = process_attr_tracker_set_tracking_policy(tracker, policy); + if (ret) { + ret_code = LTTNG_ERR_UNK; + goto end; } - /* Add to list. */ - ret = lttng_tracker_list_add(tracker_list, id); - if (ret != LTTNG_OK) { + if (previous_policy == policy) { goto end; } - switch (tracker_type) { - case LTTNG_TRACKER_PID: - DBG("Kernel track PID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_track_pid(session->fd, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } - break; - case LTTNG_TRACKER_VPID: - DBG("Kernel track VPID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VPID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } - break; - case LTTNG_TRACKER_UID: - DBG("Kernel track UID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_track_id(session->fd, LTTNG_TRACKER_UID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } - break; - case LTTNG_TRACKER_GID: - DBG("Kernel track GID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_track_id(session->fd, LTTNG_TRACKER_GID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } - break; - case LTTNG_TRACKER_VUID: - DBG("Kernel track VUID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VUID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; + switch (policy) { + case LTTNG_TRACKING_POLICY_INCLUDE_ALL: + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process + * attribute tracker as it was the only supported + * attribute prior to 2.12. + */ + ret = kernctl_track_pid(session->fd, -1); + } else { + ret = kernctl_track_id(session->fd, process_attr, -1); } break; - case LTTNG_TRACKER_VGID: - DBG("Kernel track VGID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VGID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; + case LTTNG_TRACKING_POLICY_EXCLUDE_ALL: + case LTTNG_TRACKING_POLICY_INCLUDE_SET: + /* fall-through. */ + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process + * attribute tracker as it was the only supported + * attribute prior to 2.12. + */ + ret = kernctl_untrack_pid(session->fd, -1); + } else { + ret = kernctl_untrack_id(session->fd, process_attr, -1); } break; default: - ret = -EINVAL; - break; + abort(); } - - /* Error handling. */ + /* kern-ctl error handling */ switch (-ret) { + case 0: + ret_code = LTTNG_OK; + break; case EINVAL: - ret = LTTNG_ERR_INVALID; + ret_code = LTTNG_ERR_INVALID; break; case ENOMEM: - ret = LTTNG_ERR_NOMEM; + ret_code = LTTNG_ERR_NOMEM; break; case EEXIST: - ret = LTTNG_ERR_ID_TRACKED; + ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS; break; default: - ret = LTTNG_ERR_UNK; + ret_code = LTTNG_ERR_UNK; break; } - - if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) { - ERR("Error on tracker add error handling.\n"); - } end: - lttng_tracker_ids_destroy(saved_ids); - return ret; + return ret_code; } -int kernel_untrack_id(enum lttng_tracker_type tracker_type, +enum lttng_error_code kernel_process_attr_tracker_inclusion_set_add_value( struct ltt_kernel_session *session, - const struct lttng_tracker_id *id) + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - int ret, value; - struct lttng_tracker_list *tracker_list; - struct lttng_tracker_ids *saved_ids; - - ret = lttng_tracker_id_lookup_string(tracker_type, id, &value); - if (ret != LTTNG_OK) { - return ret; - } + int ret, integral_value; + enum lttng_error_code ret_code; + struct process_attr_tracker *tracker; + enum process_attr_tracker_status status; - tracker_list = get_id_tracker_list(session, tracker_type); - if (!tracker_list) { - return LTTNG_ERR_INVALID; - } - /* Save list for restore on error. */ - ret = lttng_tracker_id_get_list(tracker_list, &saved_ids); - if (ret != LTTNG_OK) { - return LTTNG_ERR_INVALID; - } - /* Remove from list. */ - ret = lttng_tracker_list_remove(tracker_list, id); - if (ret != LTTNG_OK) { - goto end; - } - - switch (tracker_type) { - case LTTNG_TRACKER_PID: - DBG("Kernel untrack PID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_untrack_pid(session->fd, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } - break; - case LTTNG_TRACKER_VPID: - DBG("Kernel untrack VPID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_untrack_id( - session->fd, LTTNG_TRACKER_VPID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } - break; - case LTTNG_TRACKER_UID: - DBG("Kernel untrack UID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_UID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } - break; - case LTTNG_TRACKER_GID: - DBG("Kernel untrack GID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_GID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; - } + /* + * Convert process attribute tracker value to the integral + * representation required by the kern-ctl API. + */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + integral_value = (int) value->value.pid; break; - case LTTNG_TRACKER_VUID: - DBG("Kernel untrack VUID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_untrack_id( - session->fd, LTTNG_TRACKER_VUID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; + case LTTNG_PROCESS_ATTR_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) { + uid_t uid; + + ret_code = utils_user_id_from_name( + value->value.user_name, &uid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) uid; + } else { + integral_value = (int) value->value.uid; } break; - case LTTNG_TRACKER_VGID: - DBG("Kernel untrack VGID %d for session id %" PRIu64 ".", value, - session->id); - ret = kernctl_untrack_id( - session->fd, LTTNG_TRACKER_VGID, value); - if (!ret) { - ret = LTTNG_OK; - goto end; + case LTTNG_PROCESS_ATTR_GROUP_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) { + gid_t gid; + + ret_code = utils_group_id_from_name( + value->value.group_name, &gid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) gid; + } else { + integral_value = (int) value->value.gid; } break; default: - ret = -EINVAL; - break; + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + tracker = _kernel_get_process_attr_tracker(session, process_attr); + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + status = process_attr_tracker_inclusion_set_add_value(tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + switch (status) { + case PROCESS_ATTR_TRACKER_STATUS_EXISTS: + ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS; + break; + case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY: + ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY; + break; + case PROCESS_ATTR_TRACKER_STATUS_ERROR: + default: + ret_code = LTTNG_ERR_UNK; + break; + } + goto end; + } + + DBG("Kernel track %s %d for session id %" PRIu64, + lttng_process_attr_to_string(process_attr), + integral_value, session->id); + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process attribute + * tracker as it was the only supported attribute prior to 2.12. + */ + ret = kernctl_track_pid(session->fd, integral_value); + } else { + ret = kernctl_track_id( + session->fd, process_attr, integral_value); + } + if (ret == 0) { + ret_code = LTTNG_OK; + goto end; } - /* Error handling. */ + kernel_wait_quiescent(); + + /* kern-ctl error handling */ switch (-ret) { + case 0: + ret_code = LTTNG_OK; + break; case EINVAL: - ret = LTTNG_ERR_INVALID; + ret_code = LTTNG_ERR_INVALID; break; case ENOMEM: - ret = LTTNG_ERR_NOMEM; + ret_code = LTTNG_ERR_NOMEM; break; case EEXIST: - ret = LTTNG_ERR_ID_TRACKED; + ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS; break; default: - ret = LTTNG_ERR_UNK; + ret_code = LTTNG_ERR_UNK; break; } - if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) { - ERR("Error on tracker remove error handling.\n"); + /* Attempt to remove the value from the tracker. */ + status = process_attr_tracker_inclusion_set_remove_value( + tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + ERR("Failed to roll-back the tracking of kernel %s process attribute %d while handling a kern-ctl error", + lttng_process_attr_to_string(process_attr), + integral_value); } end: - lttng_tracker_ids_destroy(saved_ids); - return ret; + return ret_code; } -/* - * Called with session lock held. - */ -int kernel_list_tracker_ids(enum lttng_tracker_type tracker_type, +enum lttng_error_code kernel_process_attr_tracker_inclusion_set_remove_value( struct ltt_kernel_session *session, - struct lttng_tracker_ids **_ids) + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - int ret = 0; - struct lttng_tracker_list *tracker_list; + int ret, integral_value; + enum lttng_error_code ret_code; + struct process_attr_tracker *tracker; + enum process_attr_tracker_status status; + + /* + * Convert process attribute tracker value to the integral + * representation required by the kern-ctl API. + */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + integral_value = (int) value->value.pid; + break; + case LTTNG_PROCESS_ATTR_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) { + uid_t uid; + + ret_code = utils_user_id_from_name( + value->value.user_name, &uid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) uid; + } else { + integral_value = (int) value->value.uid; + } + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) { + gid_t gid; + + ret_code = utils_group_id_from_name( + value->value.group_name, &gid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) gid; + } else { + integral_value = (int) value->value.gid; + } + break; + default: + ret_code = LTTNG_ERR_INVALID; + goto end; + } - tracker_list = get_id_tracker_list(session, tracker_type); - if (!tracker_list) { - ret = -LTTNG_ERR_INVALID; + tracker = _kernel_get_process_attr_tracker(session, process_attr); + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; goto end; } - ret = lttng_tracker_id_get_list(tracker_list, _ids); - if (ret != LTTNG_OK) { - ret = -LTTNG_ERR_INVALID; + status = process_attr_tracker_inclusion_set_remove_value( + tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + switch (status) { + case PROCESS_ATTR_TRACKER_STATUS_MISSING: + ret_code = LTTNG_ERR_PROCESS_ATTR_MISSING; + break; + case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY: + ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY; + break; + case PROCESS_ATTR_TRACKER_STATUS_ERROR: + default: + ret_code = LTTNG_ERR_UNK; + break; + } + goto end; + } + + DBG("Kernel track %s %d for session id %" PRIu64, + lttng_process_attr_to_string(process_attr), + integral_value, session->id); + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process attribute + * tracker as it was the only supported attribute prior to 2.12. + */ + ret = kernctl_untrack_pid(session->fd, integral_value); + } else { + ret = kernctl_untrack_id( + session->fd, process_attr, integral_value); + } + if (ret == 0) { + ret_code = LTTNG_OK; goto end; } + kernel_wait_quiescent(); + /* kern-ctl error handling */ + switch (-ret) { + case 0: + ret_code = LTTNG_OK; + break; + case EINVAL: + ret_code = LTTNG_ERR_INVALID; + break; + case ENOMEM: + ret_code = LTTNG_ERR_NOMEM; + break; + case ENOENT: + ret_code = LTTNG_ERR_PROCESS_ATTR_MISSING; + break; + default: + ret_code = LTTNG_ERR_UNK; + break; + } + + /* Attempt to add the value to the tracker. */ + status = process_attr_tracker_inclusion_set_add_value( + tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + ERR("Failed to roll-back the tracking of kernel %s process attribute %d while handling a kern-ctl error", + lttng_process_attr_to_string(process_attr), + integral_value); + } end: - return ret; + return ret_code; } /* diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index 4f3bedea5..53d480313 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -8,6 +8,8 @@ #ifndef _LTT_KERNEL_CTL_H #define _LTT_KERNEL_CTL_H +#include "lttng/lttng-error.h" +#include "lttng/tracker.h" #include "session.h" #include "snapshot.h" #include "trace-kernel.h" @@ -20,7 +22,6 @@ * dynamic reallocation is performed. */ #define KERNEL_EVENT_INIT_LIST_SIZE 64 -#define KERNEL_TRACKER_IDS_INIT_LIST_SIZE 64 int kernel_add_channel_context(struct ltt_kernel_channel *chan, struct ltt_kernel_context *ctx); @@ -33,12 +34,21 @@ int kernel_disable_channel(struct ltt_kernel_channel *chan); int kernel_disable_event(struct ltt_kernel_event *event); int kernel_enable_event(struct ltt_kernel_event *event); int kernel_enable_channel(struct ltt_kernel_channel *chan); -int kernel_track_id(enum lttng_tracker_type tracker_type, +enum lttng_error_code kernel_process_attr_tracker_set_tracking_policy( struct ltt_kernel_session *session, - const struct lttng_tracker_id *id); -int kernel_untrack_id(enum lttng_tracker_type tracker_type, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy); +enum lttng_error_code kernel_process_attr_tracker_inclusion_set_add_value( struct ltt_kernel_session *session, - const struct lttng_tracker_id *id); + enum lttng_process_attr process_attr, + const struct process_attr_value *value); +enum lttng_error_code kernel_process_attr_tracker_inclusion_set_remove_value( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr, + const struct process_attr_value *value); +const struct process_attr_tracker *kernel_get_process_attr_tracker( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr); int kernel_open_metadata(struct ltt_kernel_session *session); int kernel_open_metadata_stream(struct ltt_kernel_session *session); int kernel_open_channel_stream(struct ltt_kernel_channel *channel); @@ -62,9 +72,6 @@ enum lttng_error_code kernel_rotate_session(struct ltt_session *session); enum lttng_error_code kernel_clear_session(struct ltt_session *session); int init_kernel_workarounds(void); -int kernel_list_tracker_ids(enum lttng_tracker_type tracker_type, - struct ltt_kernel_session *session, - struct lttng_tracker_ids **ids); int kernel_supports_ring_buffer_snapshot_sample_positions(void); int kernel_supports_ring_buffer_packet_sequence_number(void); int init_kernel_tracer(void); diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index f01c3186b..c3ae62791 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -1820,50 +1820,47 @@ const char *get_config_domain_str(enum lttng_domain_type domain) } /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ -static int save_id_tracker(struct config_writer *writer, +static int save_process_attr_tracker(struct config_writer *writer, struct ltt_session *sess, int domain, - enum lttng_tracker_type tracker_type) + enum lttng_process_attr process_attr) { int ret = LTTNG_OK; - unsigned int nr_ids, i; - struct lttng_tracker_ids *ids = NULL; const char *element_id_tracker, *element_target_id, *element_id; - const struct lttng_tracker_id *id; - enum lttng_tracker_id_status status; - int value; - const char *string; - - switch (tracker_type) { - case LTTNG_TRACKER_PID: - element_id_tracker = config_element_pid_tracker; - element_target_id = config_element_target_pid; - element_id = config_element_pid; - break; - case LTTNG_TRACKER_VPID: - element_id_tracker = config_element_vpid_tracker; - element_target_id = config_element_target_vpid; - element_id = config_element_id; - break; - case LTTNG_TRACKER_UID: - element_id_tracker = config_element_uid_tracker; - element_target_id = config_element_target_uid; - element_id = config_element_id; - break; - case LTTNG_TRACKER_VUID: - element_id_tracker = config_element_vuid_tracker; - element_target_id = config_element_target_vuid; - element_id = config_element_id; - break; - case LTTNG_TRACKER_GID: - element_id_tracker = config_element_gid_tracker; - element_target_id = config_element_target_gid; - element_id = config_element_id; - break; - case LTTNG_TRACKER_VGID: - element_id_tracker = config_element_vgid_tracker; - element_target_id = config_element_target_vgid; - element_id = config_element_id; + const struct process_attr_tracker *tracker; + enum lttng_tracking_policy tracking_policy; + struct lttng_process_attr_values *values = NULL; + + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + element_id_tracker = config_element_process_attr_tracker_pid; + element_target_id = config_element_process_attr_pid_value; + element_id = config_element_process_attr_id; + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + element_id_tracker = config_element_process_attr_tracker_vpid; + element_target_id = config_element_process_attr_vpid_value; + element_id = config_element_process_attr_id; + break; + case LTTNG_PROCESS_ATTR_USER_ID: + element_id_tracker = config_element_process_attr_tracker_uid; + element_target_id = config_element_process_attr_uid_value; + element_id = config_element_process_attr_id; + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + element_id_tracker = config_element_process_attr_tracker_vuid; + element_target_id = config_element_process_attr_vuid_value; + element_id = config_element_process_attr_id; + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + element_id_tracker = config_element_process_attr_tracker_gid; + element_target_id = config_element_process_attr_gid_value; + element_id = config_element_process_attr_id; + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + element_id_tracker = config_element_process_attr_tracker_vgid; + element_target_id = config_element_process_attr_vgid_value; + element_id = config_element_process_attr_id; break; default: ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -1873,61 +1870,48 @@ static int save_id_tracker(struct config_writer *writer, switch (domain) { case LTTNG_DOMAIN_KERNEL: { - ret = kernel_list_tracker_ids( - tracker_type, sess->kernel_session, &ids); - if (ret != LTTNG_OK) { - ret = LTTNG_ERR_KERN_LIST_FAIL; - goto end; - } + tracker = kernel_get_process_attr_tracker( + sess->kernel_session, process_attr); + assert(tracker); break; } case LTTNG_DOMAIN_UST: { - ret = trace_ust_list_tracker_ids( - tracker_type, sess->ust_session, &ids); - if (ret != LTTNG_OK) { - ret = LTTNG_ERR_UST_LIST_FAIL; - goto end; - } + tracker = trace_ust_get_process_attr_tracker( + sess->ust_session, process_attr); + assert(tracker); break; } case LTTNG_DOMAIN_JUL: case LTTNG_DOMAIN_LOG4J: case LTTNG_DOMAIN_PYTHON: default: - ret = LTTNG_ERR_UNKNOWN_DOMAIN; + ret = LTTNG_ERR_UNSUPPORTED_DOMAIN; goto end; } - status = lttng_tracker_ids_get_count(ids, &nr_ids); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = LTTNG_ERR_INVALID; + tracking_policy = process_attr_tracker_get_tracking_policy(tracker); + if (tracking_policy == LTTNG_TRACKING_POLICY_INCLUDE_ALL) { + /* Tracking all, nothing to output. */ + ret = LTTNG_OK; goto end; } - if (nr_ids == 1) { - id = lttng_tracker_ids_get_at_index(ids, 0); - if (id && lttng_tracker_id_get_type(id) == LTTNG_ID_ALL) { - /* Tracking all, nothing to output. */ - ret = LTTNG_OK; - goto end; - } - } - ret = config_writer_open_element(writer, element_id_tracker); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = config_writer_open_element(writer, config_element_targets); + ret = config_writer_open_element( + writer, config_element_process_attr_values); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - if (nr_ids == 0) { - /* Tracking none: empty list. */ + if (tracking_policy == LTTNG_TRACKING_POLICY_EXCLUDE_ALL) { + /* Tracking nothing; empty list. */ ret = config_writer_open_element(writer, element_target_id); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -1941,47 +1925,68 @@ static int save_id_tracker(struct config_writer *writer, goto end; } } else { - /* Tracking list. */ - for (i = 0; i < nr_ids; i++) { - id = lttng_tracker_ids_get_at_index(ids, i); - if (!id) { + unsigned int i, count; + enum process_attr_tracker_status status = + process_attr_tracker_get_inclusion_set( + tracker, &values); + + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + ret = LTTNG_ERR_NOMEM; + goto end; + } + + count = _lttng_process_attr_values_get_count(values); + + for (i = 0; i < count; i++) { + unsigned int integral_value = UINT_MAX; + const char *name = NULL; + const struct process_attr_value *value = + lttng_process_attr_tracker_values_get_at_index( + values, i); + + assert(value); + ret = config_writer_open_element( + writer, element_target_id); + if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - switch (lttng_tracker_id_get_type(id)) { - case LTTNG_ID_VALUE: - ret = config_writer_open_element( - writer, element_target_id); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - status = lttng_tracker_id_get_value(id, &value); - ret = config_writer_write_element_unsigned_int( - writer, element_id, value); + + switch (value->type) { + case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID: + integral_value = + (unsigned int) value->value.pid; break; - case LTTNG_ID_STRING: - ret = config_writer_open_element( - writer, element_target_id); - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; - } - status = lttng_tracker_id_get_string( - id, &string); - ret = config_writer_write_element_string(writer, - config_element_name, string); + case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID: + integral_value = + (unsigned int) value->value.uid; + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID: + integral_value = + (unsigned int) value->value.gid; + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME: + name = value->value.user_name; + assert(name); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME: + name = value->value.group_name; + assert(name); break; default: - /* Unexpected. */ - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; + abort(); } - if (ret) { - ret = LTTNG_ERR_SAVE_IO_FAIL; - goto end; + + if (name) { + ret = config_writer_write_element_string(writer, + config_element_name, name); + } else { + ret = config_writer_write_element_unsigned_int( + writer, element_id, + integral_value); } - if (status != LTTNG_TRACKER_ID_STATUS_OK) { + + if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } @@ -2011,12 +2016,12 @@ static int save_id_tracker(struct config_writer *writer, ret = LTTNG_OK; end: - lttng_tracker_ids_destroy(ids); + lttng_process_attr_values_destroy(values); return ret; } /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ -static int save_id_trackers(struct config_writer *writer, +static int save_process_attr_trackers(struct config_writer *writer, struct ltt_session *sess, int domain) { @@ -2024,40 +2029,60 @@ static int save_id_trackers(struct config_writer *writer, switch (domain) { case LTTNG_DOMAIN_KERNEL: - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_PID); - if (ret != LTTNG_OK) - return ret; - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VPID); - if (ret != LTTNG_OK) - return ret; - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_UID); - if (ret != LTTNG_OK) - return ret; - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VUID); - if (ret != LTTNG_OK) - return ret; - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_GID); - if (ret != LTTNG_OK) - return ret; - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VGID); - if (ret != LTTNG_OK) - return ret; + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_PROCESS_ID); + if (ret != LTTNG_OK) { + goto end; + } + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); + if (ret != LTTNG_OK) { + goto end; + } + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_USER_ID); + if (ret != LTTNG_OK) { + goto end; + } + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); + if (ret != LTTNG_OK) { + goto end; + } + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_GROUP_ID); + if (ret != LTTNG_OK) { + goto end; + } + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); + if (ret != LTTNG_OK) { + goto end; + } break; case LTTNG_DOMAIN_UST: - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VPID); - if (ret != LTTNG_OK) - return ret; - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VUID); - if (ret != LTTNG_OK) - return ret; - ret = save_id_tracker(writer, sess, domain, LTTNG_TRACKER_VGID); - if (ret != LTTNG_OK) - return ret; + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); + if (ret != LTTNG_OK) { + goto end; + } + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); + if (ret != LTTNG_OK) { + goto end; + } + ret = save_process_attr_tracker(writer, sess, domain, + LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); + if (ret != LTTNG_OK) { + goto end; + } break; default: - return LTTNG_ERR_INVALID; + ret = LTTNG_ERR_INVALID; } - return LTTNG_OK; + ret = LTTNG_OK; +end: + return ret; } /* Return LTTNG_OK on success else a LTTNG_ERR* code. */ @@ -2138,14 +2163,15 @@ int save_ust_domain(struct config_writer *writer, } if (domain == LTTNG_DOMAIN_UST) { - ret = config_writer_open_element(writer, - config_element_trackers); + ret = config_writer_open_element( + writer, config_element_process_attr_trackers); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_id_trackers(writer, session, LTTNG_DOMAIN_UST); + ret = save_process_attr_trackers( + writer, session, LTTNG_DOMAIN_UST); if (ret != LTTNG_OK) { goto end; } @@ -2202,14 +2228,15 @@ int save_domains(struct config_writer *writer, struct ltt_session *session) goto end; } - ret = config_writer_open_element(writer, - config_element_trackers); + ret = config_writer_open_element( + writer, config_element_process_attr_trackers); if (ret) { ret = LTTNG_ERR_SAVE_IO_FAIL; goto end; } - ret = save_id_trackers(writer, session, LTTNG_DOMAIN_KERNEL); + ret = save_process_attr_trackers( + writer, session, LTTNG_DOMAIN_KERNEL); if (ret != LTTNG_OK) { goto end; } diff --git a/src/bin/lttng-sessiond/trace-kernel.c b/src/bin/lttng-sessiond/trace-kernel.c index 52f819b30..723ffddd3 100644 --- a/src/bin/lttng-sessiond/trace-kernel.c +++ b/src/bin/lttng-sessiond/trace-kernel.c @@ -154,28 +154,28 @@ struct ltt_kernel_session *trace_kernel_create_session(void) lks->metadata = NULL; CDS_INIT_LIST_HEAD(&lks->channel_list.head); - lks->tracker_list_pid = lttng_tracker_list_create(); - if (!lks->tracker_list_pid) { + lks->tracker_pid = process_attr_tracker_create(); + if (!lks->tracker_pid) { goto error; } - lks->tracker_list_vpid = lttng_tracker_list_create(); - if (!lks->tracker_list_vpid) { + lks->tracker_vpid = process_attr_tracker_create(); + if (!lks->tracker_vpid) { goto error; } - lks->tracker_list_uid = lttng_tracker_list_create(); - if (!lks->tracker_list_uid) { + lks->tracker_uid = process_attr_tracker_create(); + if (!lks->tracker_uid) { goto error; } - lks->tracker_list_vuid = lttng_tracker_list_create(); - if (!lks->tracker_list_vuid) { + lks->tracker_vuid = process_attr_tracker_create(); + if (!lks->tracker_vuid) { goto error; } - lks->tracker_list_gid = lttng_tracker_list_create(); - if (!lks->tracker_list_gid) { + lks->tracker_gid = process_attr_tracker_create(); + if (!lks->tracker_gid) { goto error; } - lks->tracker_list_vgid = lttng_tracker_list_create(); - if (!lks->tracker_list_vgid) { + lks->tracker_vgid = process_attr_tracker_create(); + if (!lks->tracker_vgid) { goto error; } lks->consumer = consumer_create_output(CONSUMER_DST_LOCAL); @@ -186,12 +186,12 @@ struct ltt_kernel_session *trace_kernel_create_session(void) return lks; error: - lttng_tracker_list_destroy(lks->tracker_list_pid); - lttng_tracker_list_destroy(lks->tracker_list_vpid); - lttng_tracker_list_destroy(lks->tracker_list_uid); - lttng_tracker_list_destroy(lks->tracker_list_vuid); - lttng_tracker_list_destroy(lks->tracker_list_gid); - lttng_tracker_list_destroy(lks->tracker_list_vgid); + process_attr_tracker_destroy(lks->tracker_pid); + process_attr_tracker_destroy(lks->tracker_vpid); + process_attr_tracker_destroy(lks->tracker_uid); + process_attr_tracker_destroy(lks->tracker_vuid); + process_attr_tracker_destroy(lks->tracker_gid); + process_attr_tracker_destroy(lks->tracker_vgid); free(lks); alloc_error: @@ -738,12 +738,12 @@ void trace_kernel_free_session(struct ltt_kernel_session *session) /* Wipe consumer output object */ consumer_output_put(session->consumer); - lttng_tracker_list_destroy(session->tracker_list_pid); - lttng_tracker_list_destroy(session->tracker_list_vpid); - lttng_tracker_list_destroy(session->tracker_list_uid); - lttng_tracker_list_destroy(session->tracker_list_vuid); - lttng_tracker_list_destroy(session->tracker_list_gid); - lttng_tracker_list_destroy(session->tracker_list_vgid); + process_attr_tracker_destroy(session->tracker_pid); + process_attr_tracker_destroy(session->tracker_vpid); + process_attr_tracker_destroy(session->tracker_uid); + process_attr_tracker_destroy(session->tracker_vuid); + process_attr_tracker_destroy(session->tracker_gid); + process_attr_tracker_destroy(session->tracker_vgid); free(session); } diff --git a/src/bin/lttng-sessiond/trace-kernel.h b/src/bin/lttng-sessiond/trace-kernel.h index b290ce492..61dd8eae9 100644 --- a/src/bin/lttng-sessiond/trace-kernel.h +++ b/src/bin/lttng-sessiond/trace-kernel.h @@ -114,12 +114,12 @@ struct ltt_kernel_session { /* Current trace chunk of the ltt_session. */ struct lttng_trace_chunk *current_trace_chunk; /* Tracker lists */ - struct lttng_tracker_list *tracker_list_pid; - struct lttng_tracker_list *tracker_list_vpid; - struct lttng_tracker_list *tracker_list_uid; - struct lttng_tracker_list *tracker_list_vuid; - struct lttng_tracker_list *tracker_list_gid; - struct lttng_tracker_list *tracker_list_vgid; + struct process_attr_tracker *tracker_pid; + struct process_attr_tracker *tracker_vpid; + struct process_attr_tracker *tracker_uid; + struct process_attr_tracker *tracker_vuid; + struct process_attr_tracker *tracker_gid; + struct process_attr_tracker *tracker_vgid; }; /* diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index 92fd0de81..4432fca23 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "buffer-registry.h" #include "trace-ust.h" @@ -303,16 +304,16 @@ struct ltt_ust_session *trace_ust_create_session(uint64_t session_id) /* Alloc agent hash table. */ lus->agents = lttng_ht_new(0, LTTNG_HT_TYPE_U64); - lus->tracker_list_vpid = lttng_tracker_list_create(); - if (!lus->tracker_list_vpid) { + lus->tracker_vpid = process_attr_tracker_create(); + if (!lus->tracker_vpid) { goto error; } - lus->tracker_list_vuid = lttng_tracker_list_create(); - if (!lus->tracker_list_vuid) { + lus->tracker_vuid = process_attr_tracker_create(); + if (!lus->tracker_vuid) { goto error; } - lus->tracker_list_vgid = lttng_tracker_list_create(); - if (!lus->tracker_list_vgid) { + lus->tracker_vgid = process_attr_tracker_create(); + if (!lus->tracker_vgid) { goto error; } lus->consumer = consumer_create_output(CONSUMER_DST_LOCAL); @@ -325,9 +326,9 @@ struct ltt_ust_session *trace_ust_create_session(uint64_t session_id) return lus; error: - lttng_tracker_list_destroy(lus->tracker_list_vpid); - lttng_tracker_list_destroy(lus->tracker_list_vuid); - lttng_tracker_list_destroy(lus->tracker_list_vgid); + process_attr_tracker_destroy(lus->tracker_vpid); + process_attr_tracker_destroy(lus->tracker_vuid); + process_attr_tracker_destroy(lus->tracker_vgid); ht_cleanup_push(lus->domain_global.channels); ht_cleanup_push(lus->agents); free(lus); @@ -804,7 +805,7 @@ static int id_tracker_add_id(struct ust_id_tracker *id_tracker, int id) tracker_node = id_tracker_lookup(id_tracker, id, &iter); if (tracker_node) { /* Already exists. */ - retval = LTTNG_ERR_ID_TRACKED; + retval = LTTNG_ERR_PROCESS_ATTR_EXISTS; goto end; } tracker_node = zmalloc(sizeof(*tracker_node)); @@ -831,7 +832,7 @@ static int id_tracker_del_id(struct ust_id_tracker *id_tracker, int id) tracker_node = id_tracker_lookup(id_tracker, id, &iter); if (!tracker_node) { /* Not found */ - retval = LTTNG_ERR_ID_NOT_TRACKED; + retval = LTTNG_ERR_PROCESS_ATTR_MISSING; goto end; } ret = lttng_ht_del(id_tracker->ht, &iter); @@ -843,47 +844,56 @@ end: } static struct ust_id_tracker *get_id_tracker(struct ltt_ust_session *session, - enum lttng_tracker_type tracker_type) + enum lttng_process_attr process_attr) { - switch (tracker_type) { - case LTTNG_TRACKER_VPID: + switch (process_attr) { + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: return &session->vpid_tracker; - case LTTNG_TRACKER_VUID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: return &session->vuid_tracker; - case LTTNG_TRACKER_VGID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: return &session->vgid_tracker; default: return NULL; } } -static struct lttng_tracker_list *get_id_tracker_list( +static struct process_attr_tracker *_trace_ust_get_process_attr_tracker( struct ltt_ust_session *session, - enum lttng_tracker_type tracker_type) + enum lttng_process_attr process_attr) { - switch (tracker_type) { - case LTTNG_TRACKER_VPID: - return session->tracker_list_vpid; - case LTTNG_TRACKER_VUID: - return session->tracker_list_vuid; - case LTTNG_TRACKER_VGID: - return session->tracker_list_vgid; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + return session->tracker_vpid; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + return session->tracker_vuid; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + return session->tracker_vgid; default: return NULL; } } +const struct process_attr_tracker *trace_ust_get_process_attr_tracker( + struct ltt_ust_session *session, + enum lttng_process_attr process_attr) +{ + return (const struct process_attr_tracker *) + _trace_ust_get_process_attr_tracker( + session, process_attr); +} + /* * The session lock is held when calling this function. */ -int trace_ust_id_tracker_lookup(enum lttng_tracker_type tracker_type, +int trace_ust_id_tracker_lookup(enum lttng_process_attr process_attr, struct ltt_ust_session *session, int id) { struct lttng_ht_iter iter; struct ust_id_tracker *id_tracker; - id_tracker = get_id_tracker(session, tracker_type); + id_tracker = get_id_tracker(session, process_attr); if (!id_tracker) { abort(); } @@ -899,229 +909,283 @@ int trace_ust_id_tracker_lookup(enum lttng_tracker_type tracker_type, /* * Called with the session lock held. */ -int trace_ust_track_id(enum lttng_tracker_type tracker_type, +enum lttng_error_code trace_ust_process_attr_tracker_set_tracking_policy( struct ltt_ust_session *session, - const struct lttng_tracker_id *id) + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy) { - int retval = LTTNG_OK; + int ret; + enum lttng_error_code ret_code = LTTNG_OK; + struct ust_id_tracker *id_tracker = + get_id_tracker(session, process_attr); + struct process_attr_tracker *tracker = + _trace_ust_get_process_attr_tracker( + session, process_attr); bool should_update_apps = false; - struct ust_id_tracker *id_tracker; - struct lttng_tracker_list *tracker_list; - int value; - struct lttng_tracker_ids *saved_ids; + enum lttng_tracking_policy previous_policy; - if (tracker_type == LTTNG_TRACKER_PID) { - DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); - tracker_type = LTTNG_TRACKER_VPID; + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + goto end; } - retval = lttng_tracker_id_lookup_string(tracker_type, id, &value); - if (retval != LTTNG_OK) { - return retval; - } - tracker_list = get_id_tracker_list(session, tracker_type); - if (!tracker_list) { - return LTTNG_ERR_INVALID; - } - /* Save list for restore on error. */ - retval = lttng_tracker_id_get_list(tracker_list, &saved_ids); - if (retval != LTTNG_OK) { - return LTTNG_ERR_INVALID; - } - /* Add to list. */ - retval = lttng_tracker_list_add(tracker_list, id); - if (retval != LTTNG_OK) { + previous_policy = process_attr_tracker_get_tracking_policy(tracker); + ret = process_attr_tracker_set_tracking_policy(tracker, policy); + if (ret) { + ret_code = LTTNG_ERR_UNK; goto end; } - id_tracker = get_id_tracker(session, tracker_type); - if (!id_tracker) { - abort(); + if (previous_policy == policy) { + goto end; } - if (value == -1) { - /* Track all ids: destroy tracker if exists. */ + + switch (policy) { + case LTTNG_TRACKING_POLICY_INCLUDE_ALL: + /* Track all values: destroy tracker if exists. */ if (id_tracker->ht) { fini_id_tracker(id_tracker); /* Ensure all apps have session. */ should_update_apps = true; } - } else { - if (!id_tracker->ht) { - /* Create tracker. */ - retval = init_id_tracker(id_tracker); - if (retval != LTTNG_OK) { - ERR("Error initializing ID tracker"); - goto end_restore; - } - retval = id_tracker_add_id(id_tracker, value); - if (retval != LTTNG_OK) { - fini_id_tracker(id_tracker); - goto end_restore; - } - /* Remove all apps from session except pid. */ - should_update_apps = true; - } else { - struct ust_app *app; - - retval = id_tracker_add_id(id_tracker, value); - if (retval != LTTNG_OK) { - goto end_restore; - } - /* Add session to application */ - switch (tracker_type) { - case LTTNG_TRACKER_VPID: - app = ust_app_find_by_pid(value); - if (app) { - should_update_apps = true; - } - break; - default: - should_update_apps = true; - } + break; + case LTTNG_TRACKING_POLICY_EXCLUDE_ALL: + case LTTNG_TRACKING_POLICY_INCLUDE_SET: + /* fall-through. */ + fini_id_tracker(id_tracker); + ret_code = init_id_tracker(id_tracker); + if (ret_code != LTTNG_OK) { + ERR("Error initializing ID tracker"); + goto end; } + /* Remove all apps from session. */ + should_update_apps = true; + break; + default: + abort(); } if (should_update_apps && session->active) { ust_app_global_update_all(session); } - goto end; - -end_restore: - if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) { - ERR("Error on tracker add error handling.\n"); - } end: - lttng_tracker_ids_destroy(saved_ids); - return retval; + return ret_code; } -/* - * Called with the session lock held. - */ -int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, +/* Called with the session lock held. */ +enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_add_value( struct ltt_ust_session *session, - const struct lttng_tracker_id *id) + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - int retval = LTTNG_OK; + enum lttng_error_code ret_code = LTTNG_OK; bool should_update_apps = false; - struct ust_id_tracker *id_tracker; - struct lttng_tracker_list *tracker_list; - int value; - struct lttng_tracker_ids *saved_ids; + struct ust_id_tracker *id_tracker = + get_id_tracker(session, process_attr); + struct process_attr_tracker *tracker; + int integral_value; + enum process_attr_tracker_status status; + struct ust_app *app; - if (tracker_type == LTTNG_TRACKER_PID) { - DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); - tracker_type = LTTNG_TRACKER_VPID; - } - - retval = lttng_tracker_id_lookup_string(tracker_type, id, &value); - if (retval != LTTNG_OK) { - return retval; - } - - tracker_list = get_id_tracker_list(session, tracker_type); - if (!tracker_list) { - return LTTNG_ERR_INVALID; - } - /* Save list for restore on error. */ - retval = lttng_tracker_id_get_list(tracker_list, &saved_ids); - if (retval != LTTNG_OK) { - return LTTNG_ERR_INVALID; - } - /* Remove from list. */ - retval = lttng_tracker_list_remove(tracker_list, id); - if (retval != LTTNG_OK) { + /* + * Convert process attribute tracker value to the integral + * representation required by the kern-ctl API. + */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + integral_value = (int) value->value.pid; + break; + case LTTNG_PROCESS_ATTR_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) { + uid_t uid; + + ret_code = utils_user_id_from_name( + value->value.user_name, &uid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) uid; + } else { + integral_value = (int) value->value.uid; + } + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) { + gid_t gid; + + ret_code = utils_group_id_from_name( + value->value.group_name, &gid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) gid; + } else { + integral_value = (int) value->value.gid; + } + break; + default: + ret_code = LTTNG_ERR_INVALID; goto end; } - id_tracker = get_id_tracker(session, tracker_type); - if (!id_tracker) { - abort(); + tracker = _trace_ust_get_process_attr_tracker(session, process_attr); + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; } - if (value == -1) { - /* Create empty tracker, replace old tracker. */ - struct ust_id_tracker tmp_tracker; - - tmp_tracker = *id_tracker; - retval = init_id_tracker(id_tracker); - if (retval != LTTNG_OK) { - ERR("Error initializing ID tracker"); - /* Rollback operation. */ - *id_tracker = tmp_tracker; - goto end_restore; + status = process_attr_tracker_inclusion_set_add_value(tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + switch (status) { + case PROCESS_ATTR_TRACKER_STATUS_EXISTS: + ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS; + break; + case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY: + ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY; + break; + case PROCESS_ATTR_TRACKER_STATUS_ERROR: + default: + ret_code = LTTNG_ERR_UNK; + break; } - fini_id_tracker(&tmp_tracker); + goto end; + } - /* Remove session from all applications */ - should_update_apps = true; - } else { - struct ust_app *app; + DBG("User space track %s %d for session id %" PRIu64, + lttng_process_attr_to_string(process_attr), + integral_value, session->id); - if (!id_tracker->ht) { - /* No ID being tracked. */ - retval = LTTNG_ERR_ID_NOT_TRACKED; - goto end_restore; - } - /* Remove ID from tracker */ - retval = id_tracker_del_id(id_tracker, value); - if (retval != LTTNG_OK) { - goto end_restore; - } - switch (tracker_type) { - case LTTNG_TRACKER_VPID: - /* Remove session from application. */ - app = ust_app_find_by_pid(value); - if (app) { - should_update_apps = true; - } - break; - default: - /* Keep only apps matching ID. */ + ret_code = id_tracker_add_id(id_tracker, integral_value); + if (ret_code != LTTNG_OK) { + goto end; + } + /* Add session to application */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + app = ust_app_find_by_pid(integral_value); + if (app) { should_update_apps = true; } + break; + default: + should_update_apps = true; + break; } if (should_update_apps && session->active) { ust_app_global_update_all(session); } - goto end; - -end_restore: - if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) { - ERR("Error on tracker remove error handling.\n"); - } end: - lttng_tracker_ids_destroy(saved_ids); - return retval; + return ret_code; } -/* - * Called with session lock held. - */ -int trace_ust_list_tracker_ids(enum lttng_tracker_type tracker_type, +/* Called with the session lock held. */ +enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_remove_value( struct ltt_ust_session *session, - struct lttng_tracker_ids **_ids) + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - int ret = LTTNG_OK; - struct lttng_tracker_list *tracker_list; + enum lttng_error_code ret_code = LTTNG_OK; + bool should_update_apps = false; + struct ust_id_tracker *id_tracker = + get_id_tracker(session, process_attr); + struct process_attr_tracker *tracker; + int integral_value; + enum process_attr_tracker_status status; + struct ust_app *app; - if (tracker_type == LTTNG_TRACKER_PID) { - DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); - tracker_type = LTTNG_TRACKER_VPID; + /* + * Convert process attribute tracker value to the integral + * representation required by the kern-ctl API. + */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + integral_value = (int) value->value.pid; + break; + case LTTNG_PROCESS_ATTR_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) { + uid_t uid; + + ret_code = utils_user_id_from_name( + value->value.user_name, &uid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) uid; + } else { + integral_value = (int) value->value.uid; + } + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) { + gid_t gid; + + ret_code = utils_group_id_from_name( + value->value.group_name, &gid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) gid; + } else { + integral_value = (int) value->value.gid; + } + break; + default: + ret_code = LTTNG_ERR_INVALID; + goto end; } - tracker_list = get_id_tracker_list(session, tracker_type); - if (!tracker_list) { - ret = -LTTNG_ERR_INVALID; + tracker = _trace_ust_get_process_attr_tracker(session, process_attr); + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + } + + status = process_attr_tracker_inclusion_set_remove_value( + tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + switch (status) { + case PROCESS_ATTR_TRACKER_STATUS_MISSING: + ret_code = LTTNG_ERR_PROCESS_ATTR_MISSING; + break; + case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY: + ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY; + break; + case PROCESS_ATTR_TRACKER_STATUS_ERROR: + default: + ret_code = LTTNG_ERR_UNK; + break; + } goto end; } - ret = lttng_tracker_id_get_list(tracker_list, _ids); - if (ret != LTTNG_OK) { - ret = -LTTNG_ERR_INVALID; + DBG("User space untrack %s %d for session id %" PRIu64, + lttng_process_attr_to_string(process_attr), + integral_value, session->id); + + ret_code = id_tracker_del_id(id_tracker, integral_value); + if (ret_code != LTTNG_OK) { goto end; } + /* Add session to application */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + app = ust_app_find_by_pid(integral_value); + if (app) { + should_update_apps = true; + } + break; + default: + should_update_apps = true; + break; + } + if (should_update_apps && session->active) { + ust_app_global_update_all(session); + } end: - return ret; + return ret_code; } /* @@ -1353,9 +1417,9 @@ void trace_ust_destroy_session(struct ltt_ust_session *session) buffer_reg_uid_destroy(reg, session->consumer); } - lttng_tracker_list_destroy(session->tracker_list_vpid); - lttng_tracker_list_destroy(session->tracker_list_vuid); - lttng_tracker_list_destroy(session->tracker_list_vgid); + process_attr_tracker_destroy(session->tracker_vpid); + process_attr_tracker_destroy(session->tracker_vuid); + process_attr_tracker_destroy(session->tracker_vgid); fini_id_tracker(&session->vpid_tracker); fini_id_tracker(&session->vuid_tracker); diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index a06c471cc..ecd0b8771 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -12,9 +12,10 @@ #include #include -#include -#include #include +#include +#include +#include #include "consumer.h" #include "lttng-ust-ctl.h" @@ -137,9 +138,9 @@ struct ltt_ust_session { struct ust_id_tracker vgid_tracker; /* Tracker list of keys requested by users. */ - struct lttng_tracker_list *tracker_list_vpid; - struct lttng_tracker_list *tracker_list_vuid; - struct lttng_tracker_list *tracker_list_vgid; + struct process_attr_tracker *tracker_vpid; + struct process_attr_tracker *tracker_vuid; + struct process_attr_tracker *tracker_vgid; }; /* @@ -217,20 +218,24 @@ void trace_ust_destroy_event(struct ltt_ust_event *event); void trace_ust_destroy_context(struct ltt_ust_context *ctx); void trace_ust_free_session(struct ltt_ust_session *session); -int trace_ust_track_id(enum lttng_tracker_type tracker_type, +int trace_ust_id_tracker_lookup(enum lttng_process_attr process_attr, struct ltt_ust_session *session, - const struct lttng_tracker_id *id); -int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, + int id); +enum lttng_error_code trace_ust_process_attr_tracker_set_tracking_policy( struct ltt_ust_session *session, - const struct lttng_tracker_id *id); - -int trace_ust_id_tracker_lookup(enum lttng_tracker_type tracker_type, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy); +enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_add_value( struct ltt_ust_session *session, - int id); - -int trace_ust_list_tracker_ids(enum lttng_tracker_type tracker_type, + enum lttng_process_attr process_attr, + const struct process_attr_value *value); +enum lttng_error_code trace_ust_process_attr_tracker_inclusion_set_remove_value( + struct ltt_ust_session *session, + enum lttng_process_attr process_attr, + const struct process_attr_value *value); +const struct process_attr_tracker *trace_ust_get_process_attr_tracker( struct ltt_ust_session *session, - struct lttng_tracker_ids **_ids); + enum lttng_process_attr process_attr); #else /* HAVE_LIBLTTNG_UST_CTL */ @@ -323,32 +328,44 @@ struct agent *trace_ust_find_agent(struct ltt_ust_session *session, { return NULL; } -static inline int trace_ust_track_id(enum lttng_tracker_type tracker_type, +static inline int trace_ust_id_tracker_lookup( + enum lttng_process_attr process_attr, struct ltt_ust_session *session, - const struct lttng_tracker_id *id) + int id) { return 0; } -static inline int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, +static inline enum lttng_error_code +trace_ust_process_attr_tracker_set_tracking_policy( struct ltt_ust_session *session, - const struct lttng_tracker_id *id) + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy) { - return 0; + return LTTNG_OK; } -static inline int trace_ust_id_tracker_lookup( - enum lttng_tracker_type tracker_type, +static inline enum lttng_error_code +trace_ust_process_attr_tracker_inclusion_set_add_value( struct ltt_ust_session *session, - int pid) + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - return 0; + return LTTNG_OK; } -static inline int trace_ust_list_tracker_ids( - enum lttng_tracker_type tracker_type, +static inline enum lttng_error_code +trace_ust_process_attr_tracker_inclusion_set_remove_value( struct ltt_ust_session *session, - struct lttng_tracker_ids **_ids) + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - return -1; + return LTTNG_OK; } +static inline const struct process_attr_tracker * +trace_ust_get_process_attr_tracker(struct ltt_ust_session *session, + enum lttng_process_attr process_attr) +{ + return NULL; +} + #endif /* HAVE_LIBLTTNG_UST_CTL */ #endif /* _LTT_TRACE_UST_H */ diff --git a/src/bin/lttng-sessiond/tracker.c b/src/bin/lttng-sessiond/tracker.c index cff5af3a0..05e2fe6cd 100644 --- a/src/bin/lttng-sessiond/tracker.c +++ b/src/bin/lttng-sessiond/tracker.c @@ -1,525 +1,312 @@ /* * Copyright (C) 2018 Mathieu Desnoyers + * Copyright (C) 2020 Jérémie Galarneau * * SPDX-License-Identifier: GPL-2.0-only * */ +#include "lttng/tracker.h" +#include "common/dynamic-array.h" +#include "common/macros.h" #define _LGPL_SOURCE #include #include #include #include +#include +#include +#include #include "tracker.h" #include #include #include #include +#include #include -#include -#define FALLBACK_USER_BUFLEN 16384 -#define FALLBACK_GROUP_BUFLEN 16384 +struct process_attr_tracker_value_node { + struct process_attr_value *value; + struct cds_lfht_node inclusion_set_ht_node; + struct rcu_head rcu_head; +}; -struct lttng_tracker_list *lttng_tracker_list_create(void) +struct process_attr_tracker { + enum lttng_tracking_policy policy; + struct cds_lfht *inclusion_set_ht; +}; + +static void process_attr_tracker_value_node_rcu_free(struct rcu_head *rcu_head) +{ + struct process_attr_tracker_value_node *node = + container_of(rcu_head, typeof(*node), rcu_head); + + free(node); +} + +struct process_attr_tracker *process_attr_tracker_create(void) { - struct lttng_tracker_list *t; + struct process_attr_tracker *tracker; - t = zmalloc(sizeof(*t)); - if (!t) { + tracker = zmalloc(sizeof(*tracker)); + if (!tracker) { return NULL; } - t->ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0, + + (void) process_attr_tracker_set_tracking_policy( + tracker, LTTNG_TRACKING_POLICY_INCLUDE_ALL); + + tracker->inclusion_set_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL); - if (!t->ht) { + if (!tracker->inclusion_set_ht) { goto error; } - CDS_INIT_LIST_HEAD(&t->list_head); - t->state = LTTNG_TRACK_ALL; - return t; + return tracker; error: - free(t); + process_attr_tracker_destroy(tracker); return NULL; } -static int match_tracker_key(struct cds_lfht_node *node, const void *key) +static void process_attr_tracker_remove_value_node( + struct process_attr_tracker *tracker, + struct process_attr_tracker_value_node *value_node) { - const struct lttng_tracker_id *tracker_key = key; - struct lttng_tracker_list_node *tracker_node; - - tracker_node = caa_container_of( - node, struct lttng_tracker_list_node, ht_node); - - return lttng_tracker_id_is_equal(tracker_node->id, tracker_key); + cds_lfht_del(tracker->inclusion_set_ht, + &value_node->inclusion_set_ht_node); + process_attr_value_destroy(value_node->value); + call_rcu(&value_node->rcu_head, + process_attr_tracker_value_node_rcu_free); } -static unsigned long hash_tracker_key( - const struct lttng_tracker_id *tracker_key) +static void process_attr_tracker_clear_inclusion_set( + struct process_attr_tracker *tracker) { - unsigned long key_hash = 0; - int value; - const char *string; - enum lttng_tracker_id_type type; - - /* We do not care for invalid state during hash computation */ - type = lttng_tracker_id_get_type(tracker_key); - (void) lttng_tracker_id_get_value(tracker_key, &value); - (void) lttng_tracker_id_get_string(tracker_key, &string); - - switch (type) { - case LTTNG_ID_ALL: - break; - case LTTNG_ID_VALUE: - key_hash ^= hash_key_ulong( - (void *) (unsigned long) value, lttng_ht_seed); - break; - case LTTNG_ID_STRING: - key_hash ^= hash_key_str(string, lttng_ht_seed); - break; - case LTTNG_ID_UNKNOWN: - break; - } - key_hash ^= hash_key_ulong( - (void *) (unsigned long) type, lttng_ht_seed); - return key_hash; -} + int ret; + struct lttng_ht_iter iter; + struct process_attr_tracker_value_node *value_node; -static struct lttng_tracker_id **lttng_tracker_list_lookup( - const struct lttng_tracker_list *tracker_list, - const struct lttng_tracker_id *key) -{ - struct lttng_tracker_list_node *list_node; - struct cds_lfht_iter iter; - struct cds_lfht_node *node; + if (!tracker->inclusion_set_ht) { + return; + } - cds_lfht_lookup(tracker_list->ht, hash_tracker_key(key), - match_tracker_key, key, &iter); - node = cds_lfht_iter_get_node(&iter); - if (!node) { - return NULL; + rcu_read_lock(); + cds_lfht_for_each_entry (tracker->inclusion_set_ht, &iter.iter, + value_node, inclusion_set_ht_node) { + process_attr_tracker_remove_value_node(tracker, value_node); } - list_node = caa_container_of( - node, struct lttng_tracker_list_node, ht_node); - return &list_node->id; + rcu_read_unlock(); + ret = cds_lfht_destroy(tracker->inclusion_set_ht, NULL); + assert(ret == 0); + tracker->inclusion_set_ht = NULL; } -static void destroy_list_node_rcu(struct rcu_head *head) +static int process_attr_tracker_create_inclusion_set( + struct process_attr_tracker *tracker) { - struct lttng_tracker_list_node *n = caa_container_of( - head, struct lttng_tracker_list_node, rcu_head); - - lttng_tracker_id_destroy(n->id); - free(n); + assert(!tracker->inclusion_set_ht); + tracker->inclusion_set_ht = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0, + CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL); + return tracker->inclusion_set_ht ? 0 : -1; } -static void _lttng_tracker_list_remove(struct lttng_tracker_list *tracker_list, - struct lttng_tracker_list_node *n) +void process_attr_tracker_destroy(struct process_attr_tracker *tracker) { - cds_list_del(&n->list_node); - - rcu_read_lock(); - cds_lfht_del(tracker_list->ht, &n->ht_node); - rcu_read_unlock(); + if (!tracker) { + return; + } - call_rcu(&n->rcu_head, destroy_list_node_rcu); + process_attr_tracker_clear_inclusion_set(tracker); + free(tracker); } -static void lttng_tracker_list_reset(struct lttng_tracker_list *tracker_list) +enum lttng_tracking_policy process_attr_tracker_get_tracking_policy( + const struct process_attr_tracker *tracker) { - struct lttng_tracker_list_node *n, *t; - - cds_list_for_each_entry_safe ( - n, t, &tracker_list->list_head, list_node) { - _lttng_tracker_list_remove(tracker_list, n); - } - tracker_list->state = LTTNG_TRACK_ALL; + return tracker->policy; } -/* Protected by session mutex held by caller. */ -int lttng_tracker_list_add(struct lttng_tracker_list *tracker_list, - const struct lttng_tracker_id *_id) +int process_attr_tracker_set_tracking_policy( + struct process_attr_tracker *tracker, + enum lttng_tracking_policy tracking_policy) { - struct lttng_tracker_id **id; - struct lttng_tracker_list_node *n = NULL; - int ret; + int ret = 0; - if (lttng_tracker_id_get_type(_id) == LTTNG_ID_ALL) { - /* Track all, so remove each individual item. */ - lttng_tracker_list_reset(tracker_list); - ret = LTTNG_OK; - goto error; - } - rcu_read_lock(); - id = lttng_tracker_list_lookup(tracker_list, _id); - /* - * It is okay to release the RCU read lock here since id is only checked - * for != NULL and not dereferenced. - */ - rcu_read_unlock(); - if (id) { - ret = LTTNG_ERR_ID_TRACKED; - goto error; - } - n = zmalloc(sizeof(*n)); - if (!n) { - ret = LTTNG_ERR_NOMEM; - goto error; + if (tracker->policy == tracking_policy) { + goto end; } - n->id = lttng_tracker_id_duplicate(_id); - if (!n->id) { - ret = LTTNG_ERR_NOMEM; - goto error; + process_attr_tracker_clear_inclusion_set(tracker); + ret = process_attr_tracker_create_inclusion_set(tracker); + if (ret) { + goto end; } - - cds_list_add_tail(&n->list_node, &tracker_list->list_head); - tracker_list->state = LTTNG_TRACK_LIST; - - rcu_read_lock(); - cds_lfht_add(tracker_list->ht, hash_tracker_key(n->id), &n->ht_node); - rcu_read_unlock(); - - return LTTNG_OK; - -error: - free(n); + tracker->policy = tracking_policy; +end: return ret; } -/* - * Lookup and remove. - * Protected by session mutex held by caller. - */ -int lttng_tracker_list_remove(struct lttng_tracker_list *tracker_list, - const struct lttng_tracker_id *_id) +static int match_inclusion_set_value( + struct cds_lfht_node *node, const void *key) { - enum lttng_error_code ret = LTTNG_OK; - struct lttng_tracker_id **id; - struct lttng_tracker_list_node *n; - - if (lttng_tracker_id_get_type(_id) == LTTNG_ID_ALL) { - /* Untrack all. */ - lttng_tracker_list_reset(tracker_list); - /* Set state to "track none". */ - tracker_list->state = LTTNG_TRACK_NONE; - goto end; - } + const struct process_attr_value *value_key = key; + const struct process_attr_tracker_value_node *value_node = + caa_container_of(node, + struct process_attr_tracker_value_node, + inclusion_set_ht_node); - rcu_read_lock(); - id = lttng_tracker_list_lookup(tracker_list, _id); - if (!id) { - ret = LTTNG_ERR_ID_NOT_TRACKED; - goto rcu_unlock; - } + return process_attr_tracker_value_equal(value_node->value, value_key); +} - n = caa_container_of(id, struct lttng_tracker_list_node, id); - _lttng_tracker_list_remove(tracker_list, n); +static struct process_attr_tracker_value_node *process_attr_tracker_lookup( + const struct process_attr_tracker *tracker, + const struct process_attr_value *value) +{ + struct cds_lfht_iter iter; + struct cds_lfht_node *node; -rcu_unlock: + assert(tracker->policy == LTTNG_TRACKING_POLICY_INCLUDE_SET); + + rcu_read_lock(); + cds_lfht_lookup(tracker->inclusion_set_ht, + process_attr_value_hash(value), + match_inclusion_set_value, value, &iter); + node = cds_lfht_iter_get_node(&iter); rcu_read_unlock(); -end: - return ret; + + return node ? container_of(node, struct process_attr_tracker_value_node, + inclusion_set_ht_node) : + NULL; } -void lttng_tracker_list_destroy(struct lttng_tracker_list *tracker_list) +/* Protected by session mutex held by caller. */ +enum process_attr_tracker_status process_attr_tracker_inclusion_set_add_value( + struct process_attr_tracker *tracker, + const struct process_attr_value *value) { - int ret; + enum process_attr_tracker_status status = + PROCESS_ATTR_TRACKER_STATUS_OK; + struct process_attr_value *value_copy = NULL; + struct process_attr_tracker_value_node *value_node = NULL; - if (!tracker_list) { - return; + rcu_read_lock(); + if (tracker->policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) { + status = PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY; + goto end; } - lttng_tracker_list_reset(tracker_list); - ret = cds_lfht_destroy(tracker_list->ht, NULL); - assert(!ret); - free(tracker_list); -} -static int lttng_lookup_user(const char *username, int *result) -{ - struct passwd p, *pres; - int ret, retval = LTTNG_OK; - char *buf = NULL; - ssize_t buflen; - - buflen = sysconf(_SC_GETPW_R_SIZE_MAX); - if (buflen < 0) { - buflen = FALLBACK_USER_BUFLEN; - } - buf = zmalloc(buflen); - if (!buf) { - retval = LTTNG_ERR_NOMEM; + if (process_attr_tracker_lookup(tracker, value)) { + status = PROCESS_ATTR_TRACKER_STATUS_EXISTS; goto end; } - for (;;) { - ret = getpwnam_r(username, &p, buf, buflen, &pres); - switch (ret) { - case EINTR: - continue; - case ERANGE: - buflen *= 2; - free(buf); - buf = zmalloc(buflen); - if (!buf) { - retval = LTTNG_ERR_NOMEM; - goto end; - } - continue; - default: - goto end_loop; - } - } -end_loop: - - switch (ret) { - case 0: - if (pres == NULL) { - retval = LTTNG_ERR_USER_NOT_FOUND; - } else { - *result = (int) p.pw_uid; - DBG("Lookup of tracker UID/VUID: name '%s' maps to id %d.", - username, *result); - retval = LTTNG_OK; - } - break; - case ENOENT: - case ESRCH: - case EBADF: - case EPERM: - retval = LTTNG_ERR_USER_NOT_FOUND; - break; - default: - retval = LTTNG_ERR_NOMEM; - } -end: - free(buf); - return retval; -} -static int lttng_lookup_group(const char *groupname, int *result) -{ - struct group g, *gres; - int ret, retval = LTTNG_OK; - char *buf = NULL; - ssize_t buflen; - - buflen = sysconf(_SC_GETGR_R_SIZE_MAX); - if (buflen < 0) { - buflen = FALLBACK_GROUP_BUFLEN; + value_node = zmalloc(sizeof(*value_node)); + if (!value_node) { + status = PROCESS_ATTR_TRACKER_STATUS_ERROR; + goto end; } - buf = zmalloc(buflen); - if (!buf) { - retval = LTTNG_ERR_NOMEM; + + value_copy = process_attr_value_copy(value); + if (!value_copy) { + status = PROCESS_ATTR_TRACKER_STATUS_ERROR; goto end; } - for (;;) { - ret = getgrnam_r(groupname, &g, buf, buflen, &gres); - switch (ret) { - case EINTR: - continue; - case ERANGE: - buflen *= 2; - free(buf); - buf = zmalloc(buflen); - if (!buf) { - retval = LTTNG_ERR_NOMEM; - goto end; - } - continue; - default: - goto end_loop; - } + + value_node->value = value_copy; + cds_lfht_add(tracker->inclusion_set_ht, + process_attr_value_hash(value_copy), + &value_node->inclusion_set_ht_node); + value_copy = NULL; + value_node = NULL; +end: + if (value_copy) { + process_attr_value_destroy(value_copy); } -end_loop: - - switch (ret) { - case 0: - if (gres == NULL) { - retval = LTTNG_ERR_GROUP_NOT_FOUND; - } else { - *result = (int) g.gr_gid; - DBG("Lookup of tracker GID/GUID: name '%s' maps to id %d.", - groupname, *result); - retval = LTTNG_OK; - } - break; - case ENOENT: - case ESRCH: - case EBADF: - case EPERM: - retval = LTTNG_ERR_GROUP_NOT_FOUND; - break; - default: - retval = LTTNG_ERR_NOMEM; + if (value_node) { + free(value_node); } -end: - free(buf); - return retval; + rcu_read_unlock(); + return status; } -int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id, - int *result) +/* Protected by session mutex held by caller. */ +enum process_attr_tracker_status +process_attr_tracker_inclusion_set_remove_value( + struct process_attr_tracker *tracker, + const struct process_attr_value *value) { - enum lttng_tracker_id_status status; - int value; - const char *string; - - switch (lttng_tracker_id_get_type(id)) { - case LTTNG_ID_ALL: - *result = -1; - return LTTNG_OK; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_get_value(id, &value); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - return LTTNG_ERR_INVALID; - } - *result = id->value; - return LTTNG_OK; - case LTTNG_ID_STRING: - status = lttng_tracker_id_get_string(id, &string); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - return LTTNG_ERR_INVALID; - } - switch (tracker_type) { - case LTTNG_TRACKER_PID: - case LTTNG_TRACKER_VPID: - ERR("Lookup of tracker PID/VPID by name unsupported."); - return LTTNG_ERR_INVALID; - case LTTNG_TRACKER_UID: - case LTTNG_TRACKER_VUID: - DBG("Lookup of tracker UID/VUID by name."); - return lttng_lookup_user(string, result); - case LTTNG_TRACKER_GID: - case LTTNG_TRACKER_VGID: - DBG("Lookup of tracker GID/VGID by name."); - return lttng_lookup_group(string, result); - default: - return LTTNG_ERR_INVALID; - } - default: - return LTTNG_ERR_INVALID; - } -} + struct process_attr_tracker_value_node *value_node; + enum process_attr_tracker_status status = + PROCESS_ATTR_TRACKER_STATUS_OK; -/* - * Protected by session mutex held by caller. - * On success, _ids and the ids it contains must be freed by the caller. - */ -int lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list, - struct lttng_tracker_ids **_ids) -{ - int retval = LTTNG_OK, ret; - struct lttng_tracker_list_node *n; - ssize_t count = 0, i = 0; - struct lttng_tracker_ids *ids = NULL; - struct lttng_tracker_id *id; - enum lttng_tracker_id_status status; - - switch (tracker_list->state) { - case LTTNG_TRACK_LIST: - cds_list_for_each_entry ( - n, &tracker_list->list_head, list_node) { - count++; - } - ids = lttng_tracker_ids_create(count); - if (ids == NULL) { - PERROR("Failed to allocate tracked ID list"); - retval = -LTTNG_ERR_NOMEM; - goto end; - } - cds_list_for_each_entry ( - n, &tracker_list->list_head, list_node) { - id = lttng_tracker_ids_get_pointer_of_index(ids, i); - if (!id) { - retval = -LTTNG_ERR_INVALID; - goto error; - } - - ret = lttng_tracker_id_copy(id, n->id); - if (ret) { - retval = -LTTNG_ERR_NOMEM; - goto error; - } - i++; - } - break; - case LTTNG_TRACK_ALL: - - ids = lttng_tracker_ids_create(1); - if (ids == NULL) { - PERROR("Failed to allocate tracked ID list"); - retval = -LTTNG_ERR_NOMEM; - goto end; - } + rcu_read_lock(); + if (tracker->policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) { + status = PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY; + goto end; + } - id = lttng_tracker_ids_get_pointer_of_index(ids, 0); - status = lttng_tracker_id_set_all(id); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ERR("Invalid tracker id for track all"); - retval = -LTTNG_ERR_INVALID; - goto error; - } - break; - case LTTNG_TRACK_NONE: - /* No ids track, so we return 0 element collection. */ - ids = lttng_tracker_ids_create(0); - if (ids == NULL) { - PERROR("alloc list ids"); - retval = -LTTNG_ERR_NOMEM; - goto end; - } - break; + value_node = process_attr_tracker_lookup(tracker, value); + if (!value_node) { + status = PROCESS_ATTR_TRACKER_STATUS_MISSING; + goto end; } - *_ids = ids; + process_attr_tracker_remove_value_node(tracker, value_node); end: - return retval; - -error: - lttng_tracker_ids_destroy(ids); - return retval; + rcu_read_unlock(); + return status; } -int lttng_tracker_id_set_list(struct lttng_tracker_list *tracker_list, - const struct lttng_tracker_ids *ids) +enum process_attr_tracker_status process_attr_tracker_get_inclusion_set( + const struct process_attr_tracker *tracker, + struct lttng_process_attr_values **_values) { - unsigned int i, count; - const struct lttng_tracker_id *id; - enum lttng_tracker_id_status status; - - assert(tracker_list); - assert(ids); - - lttng_tracker_list_reset(tracker_list); - - status = lttng_tracker_ids_get_count(ids, &count); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - return LTTNG_ERR_INVALID; + struct lttng_ht_iter iter; + struct process_attr_tracker_value_node *value_node; + enum process_attr_tracker_status status = + PROCESS_ATTR_TRACKER_STATUS_OK; + struct lttng_process_attr_values *values; + struct process_attr_value *new_value = NULL; + + values = lttng_process_attr_values_create(); + if (!values) { + status = PROCESS_ATTR_TRACKER_STATUS_ERROR; + goto error; } - if (count == 0) { - /* Set state to "track none". */ - tracker_list->state = LTTNG_TRACK_NONE; - return LTTNG_OK; + if (tracker->policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) { + status = PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY; + goto error; } - if (count == 1) { - id = lttng_tracker_ids_get_at_index(ids, 0); - if (lttng_tracker_id_get_type(id) == LTTNG_ID_ALL) { - /* Track all. */ - return LTTNG_OK; + rcu_read_lock(); + cds_lfht_for_each_entry (tracker->inclusion_set_ht, &iter.iter, + value_node, inclusion_set_ht_node) { + int ret; + + new_value = process_attr_value_copy(value_node->value); + if (!new_value) { + status = PROCESS_ATTR_TRACKER_STATUS_ERROR; + goto error_unlock; } - } - for (i = 0; i < count; i++) { - int ret; - id = lttng_tracker_ids_get_at_index(ids, i); - ret = lttng_tracker_list_add(tracker_list, id); - if (ret != LTTNG_OK) { - return ret; + ret = lttng_dynamic_pointer_array_add_pointer( + &values->array, new_value); + if (ret) { + status = PROCESS_ATTR_TRACKER_STATUS_ERROR; + goto error_unlock; } + + new_value = NULL; } - return LTTNG_OK; + rcu_read_unlock(); + *_values = values; + return status; +error_unlock: + rcu_read_unlock(); +error: + lttng_process_attr_values_destroy(values); + process_attr_value_destroy(new_value); + return status; } diff --git a/src/bin/lttng-sessiond/tracker.h b/src/bin/lttng-sessiond/tracker.h index 78a12a6c7..a45a250bb 100644 --- a/src/bin/lttng-sessiond/tracker.h +++ b/src/bin/lttng-sessiond/tracker.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 Mathieu Desnoyers + * Copyright (C) 2020 Jérémie Galarneau * * SPDX-License-Identifier: GPL-2.0-only * @@ -8,47 +9,38 @@ #ifndef _LTT_TRACKER_H #define _LTT_TRACKER_H +#include #include -#include -#include -#include - -enum lttng_tracker_list_state { - LTTNG_TRACK_ALL, - LTTNG_TRACK_NONE, - LTTNG_TRACK_LIST, -}; - -/* Tracker ID */ -struct lttng_tracker_list_node { - struct lttng_tracker_id *id; - struct cds_list_head list_node; - struct cds_lfht_node ht_node; - struct rcu_head rcu_head; -}; +struct process_attr_tracker; -struct lttng_tracker_list { - struct cds_list_head list_head; - /* Hash table for O(1) removal lookup. */ - struct cds_lfht *ht; - enum lttng_tracker_list_state state; +enum process_attr_tracker_status { + PROCESS_ATTR_TRACKER_STATUS_OK, + PROCESS_ATTR_TRACKER_STATUS_ERROR, + PROCESS_ATTR_TRACKER_STATUS_EXISTS, + PROCESS_ATTR_TRACKER_STATUS_MISSING, + PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY, }; -struct lttng_tracker_list *lttng_tracker_list_create(void); -void lttng_tracker_list_destroy(struct lttng_tracker_list *tracker_list); - -int lttng_tracker_list_add(struct lttng_tracker_list *tracker_list, - const struct lttng_tracker_id *id); -int lttng_tracker_list_remove(struct lttng_tracker_list *tracker_list, - const struct lttng_tracker_id *id); - -int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id, - int *result); -int lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list, - struct lttng_tracker_ids **_ids); -int lttng_tracker_id_set_list(struct lttng_tracker_list *tracker_list, - const struct lttng_tracker_ids *_ids); +struct process_attr_tracker *process_attr_tracker_create(void); +void process_attr_tracker_destroy(struct process_attr_tracker *tracker); + +enum lttng_tracking_policy process_attr_tracker_get_tracking_policy( + const struct process_attr_tracker *tracker); +int process_attr_tracker_set_tracking_policy( + struct process_attr_tracker *tracker, + enum lttng_tracking_policy tracking_policy); + +enum process_attr_tracker_status process_attr_tracker_inclusion_set_add_value( + struct process_attr_tracker *tracker, + const struct process_attr_value *value); +enum process_attr_tracker_status +process_attr_tracker_inclusion_set_remove_value( + struct process_attr_tracker *tracker, + const struct process_attr_value *value); + +enum process_attr_tracker_status process_attr_tracker_get_inclusion_set( + const struct process_attr_tracker *tracker, + struct lttng_process_attr_values **values); #endif /* _LTT_TRACKER_H */ diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index ba63922cb..ea3f86039 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -5116,11 +5116,14 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app) if (!app->compatible) { return; } - if (trace_ust_id_tracker_lookup(LTTNG_TRACKER_VPID, usess, app->pid) && + if (trace_ust_id_tracker_lookup(LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID, + usess, app->pid) && trace_ust_id_tracker_lookup( - LTTNG_TRACKER_VUID, usess, app->uid) && + LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID, + usess, app->uid) && trace_ust_id_tracker_lookup( - LTTNG_TRACKER_VGID, usess, app->gid)) { + LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID, + usess, app->gid)) { /* * Synchronize the application's internal tracing configuration * and start tracing. diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index 334d4daf1..70dc99b0a 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -1,10 +1,12 @@ /* * Copyright (C) 2011 David Goulet + * Copyright (C) 2020 Jérémie Galarneau * * SPDX-License-Identifier: GPL-2.0-only * */ +#include #define _LGPL_SOURCE #include #include @@ -15,6 +17,7 @@ #include #include +#include #include #include @@ -1503,140 +1506,274 @@ error_channels: return ret; } -static const char *get_tracker_str(enum lttng_tracker_type tracker_type) +static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr) { - switch (tracker_type) { - case LTTNG_TRACKER_PID: - return "PID"; - case LTTNG_TRACKER_VPID: - return "VPID"; - case LTTNG_TRACKER_UID: - return "UID"; - case LTTNG_TRACKER_VUID: - return "VUID"; - case LTTNG_TRACKER_GID: - return "GID"; - case LTTNG_TRACKER_VGID: - return "VGID"; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + return "Process ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + return "Virtual process ID"; + case LTTNG_PROCESS_ATTR_USER_ID: + return "User ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + return "Virtual user ID"; + case LTTNG_PROCESS_ATTR_GROUP_ID: + return "Group ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + return "Virtual group ID"; + default: + return "Unknown"; } return NULL; } +static int handle_process_attr_status(enum lttng_process_attr process_attr, + enum lttng_process_attr_tracker_handle_status status) +{ + int ret = CMD_SUCCESS; + + switch (status) { + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY: + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: + /* Carry on. */ + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR: + ERR("Communication occurred while fetching %s tracker", + lttng_process_attr_to_string(process_attr)); + ret = CMD_ERROR; + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST: + ERR("Failed to get the inclusion set of the %s tracker: session `%s` no longer exists", + lttng_process_attr_to_string(process_attr), + handle->session_name); + ret = CMD_ERROR; + break; + default: + ERR("Unknown error occurred while fetching the inclusion set of the %s tracker", + lttng_process_attr_to_string(process_attr)); + ret = CMD_ERROR; + break; + } + + return ret; +} + +static int mi_output_empty_tracker(enum lttng_process_attr process_attr) +{ + int ret; + + ret = mi_lttng_process_attribute_tracker_open(writer, process_attr); + if (ret) { + goto end; + } + + ret = mi_lttng_close_multi_element(writer, 2); +end: + return ret; +} + +static inline bool is_value_type_name( + enum lttng_process_attr_value_type value_type) +{ + return value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME || + value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME; +} + /* - * List tracker ID(s) of session and domain. + * List a process attribute tracker for a session and domain tuple. */ -static int list_tracker_ids(enum lttng_tracker_type tracker_type) +static int list_process_attr_tracker(enum lttng_process_attr process_attr) { int ret = 0; - int enabled = 1; - struct lttng_tracker_ids *ids = NULL; - unsigned int nr_ids, i; - const struct lttng_tracker_id *id; - enum lttng_tracker_id_status status; + unsigned int count, i; + enum lttng_tracking_policy policy; + enum lttng_error_code ret_code; + enum lttng_process_attr_tracker_handle_status handle_status; + enum lttng_process_attr_values_status values_status; + const struct lttng_process_attr_values *values; + struct lttng_process_attr_tracker_handle *tracker_handle = NULL; + + ret_code = lttng_session_get_tracker_handle(handle->session_name, + handle->domain.type, process_attr, &tracker_handle); + if (ret_code != LTTNG_OK) { + ERR("Failed to get process attribute tracker handle: %s", + lttng_strerror(ret_code)); + ret = CMD_ERROR; + goto end; + } - ret = lttng_list_tracker_ids(handle, tracker_type, &ids); - if (ret) { - return ret; + handle_status = lttng_process_attr_tracker_handle_get_inclusion_set( + tracker_handle, &values); + ret = handle_process_attr_status(process_attr, handle_status); + if (ret != CMD_SUCCESS) { + goto end; } - status = lttng_tracker_ids_get_count(ids, &nr_ids); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = CMD_ERROR; + handle_status = lttng_process_attr_tracker_handle_get_tracking_policy( + tracker_handle, &policy); + ret = handle_process_attr_status(process_attr, handle_status); + if (ret != CMD_SUCCESS) { goto end; } - if (nr_ids == 1) { - id = lttng_tracker_ids_get_at_index(ids, 0); - if (id && lttng_tracker_id_get_type(id) == LTTNG_ID_ALL) { - enabled = 0; + { + char *process_attr_name; + const int print_ret = asprintf(&process_attr_name, "%ss:", + get_capitalized_process_attr_str(process_attr)); + + if (print_ret == -1) { + ret = CMD_FATAL; + goto end; } + _MSG(" %-22s", process_attr_name); + free(process_attr_name); + } + switch (policy) { + case LTTNG_TRACKING_POLICY_INCLUDE_SET: + break; + case LTTNG_TRACKING_POLICY_EXCLUDE_ALL: + if (writer) { + mi_output_empty_tracker(process_attr); + } + MSG("none"); + ret = CMD_SUCCESS; + goto end; + case LTTNG_TRACKING_POLICY_INCLUDE_ALL: + MSG("all"); + ret = CMD_SUCCESS; + goto end; + default: + ERR("Unknown tracking policy encoutered while listing the %s process attribute tracker of session `%s`", + lttng_process_attr_to_string(process_attr), + handle->session_name); + ret = CMD_FATAL; + goto end; } - if (enabled) { - _MSG("%s tracker: [", get_tracker_str(tracker_type)); + values_status = lttng_process_attr_values_get_count(values, &count); + if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) { + ERR("Failed to get the count of values in the inclusion set of the %s process attribute tracker of session `%s`", + lttng_process_attr_to_string(process_attr), + handle->session_name); + ret = CMD_FATAL; + goto end; + } - /* Mi tracker_id element */ + if (count == 0) { + /* Functionally equivalent to the 'exclude all' policy. */ if (writer) { - /* Open tracker_id and targets elements */ - ret = mi_lttng_id_tracker_open(writer, tracker_type); - if (ret) { - goto end; - } + mi_output_empty_tracker(process_attr); } + MSG("none"); + ret = CMD_SUCCESS; + goto end; + } - for (i = 0; i < nr_ids; i++) { - enum lttng_tracker_id_status status = - LTTNG_TRACKER_ID_STATUS_OK; - int value; - const char *value_string; + /* Mi tracker_id element */ + if (writer) { + /* Open tracker_id and targets elements */ + ret = mi_lttng_process_attribute_tracker_open( + writer, process_attr); + if (ret) { + goto end; + } + } - id = lttng_tracker_ids_get_at_index(ids, i); - if (!id) { - ret = CMD_ERROR; - goto end; - } + for (i = 0; i < count; i++) { + const enum lttng_process_attr_value_type value_type = + lttng_process_attr_values_get_type_at_index( + values, i); + int64_t integral_value = INT64_MAX; + const char *name = "error"; + + if (i >= 1) { + _MSG(", "); + } + switch (value_type) { + case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID: + { + pid_t pid; + + values_status = lttng_process_attr_values_get_pid_at_index( + values, i, &pid); + integral_value = (int64_t) pid; + break; + } + case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID: + { + uid_t uid; - switch (lttng_tracker_id_get_type(id)) { - case LTTNG_ID_ALL: - break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_get_value(id, &value); - break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_get_string( - id, &value_string); - break; - case LTTNG_ID_UNKNOWN: - ret = CMD_ERROR; - goto end; - } + values_status = lttng_process_attr_values_get_uid_at_index( + values, i, &uid); + integral_value = (int64_t) uid; + break; + } + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID: + { + gid_t gid; - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ERR("Invalid state for tracker id"); - ret = CMD_ERROR; - goto end; - } + values_status = lttng_process_attr_values_get_gid_at_index( + values, i, &gid); + integral_value = (int64_t) gid; + break; + } + case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME: + values_status = lttng_process_attr_values_get_user_name_at_index( + values, i, &name); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME: + values_status = lttng_process_attr_values_get_group_name_at_index( + values, i, &name); + break; + default: + ret = CMD_ERROR; + goto end; + } - if (i) { - _MSG(","); - } - switch (lttng_tracker_id_get_type(id)) { - case LTTNG_ID_ALL: - _MSG(" *"); - break; - case LTTNG_ID_VALUE: - _MSG(" %d", value); - break; - case LTTNG_ID_STRING: - _MSG(" %s", value_string); - break; - case LTTNG_ID_UNKNOWN: - ERR("Invalid state for tracker id"); - ret = CMD_ERROR; - goto end; - } + if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) { + /* + * Not possible given the current liblttng-ctl + * implementation. + */ + ERR("Unknown error occurred while fetching process attribute value in inclusion list"); + ret = CMD_FATAL; + goto end; + } - /* Mi */ - if (writer) { - ret = mi_lttng_id_target( - writer, tracker_type, id, 0); - if (ret) { - goto end; - } - } + if (is_value_type_name(value_type)) { + _MSG("`%s`", name); + } else { + _MSG("%" PRIi64, integral_value); } - _MSG(" ]\n\n"); - /* Mi close tracker_id and targets */ + /* Mi */ if (writer) { - ret = mi_lttng_close_multi_element(writer, 2); + ret = is_value_type_name(value_type) ? + mi_lttng_string_process_attribute_value( + writer, + process_attr, + name, false) : + mi_lttng_integral_process_attribute_value( + writer, + process_attr, + integral_value, + false); if (ret) { goto end; } } } + MSG(""); + + /* Mi close tracker_id and targets */ + if (writer) { + ret = mi_lttng_close_multi_element(writer, 2); + if (ret) { + goto end; + } + } end: - lttng_tracker_ids_destroy(ids); + lttng_process_attr_tracker_handle_destroy(tracker_handle); return ret; } @@ -1647,6 +1784,7 @@ static int list_trackers(const struct lttng_domain *domain) { int ret = 0; + MSG("Tracked process attributes"); /* Trackers listing */ if (lttng_opt_mi) { ret = mi_lttng_trackers_open(writer); @@ -1658,49 +1796,55 @@ static int list_trackers(const struct lttng_domain *domain) switch (domain->type) { case LTTNG_DOMAIN_KERNEL: /* pid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_PID); + ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_PROCESS_ID); if (ret) { goto end; } /* vpid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_VPID); + ret = list_process_attr_tracker( + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); if (ret) { goto end; } /* uid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_UID); + ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_USER_ID); if (ret) { goto end; } /* vuid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_VUID); + ret = list_process_attr_tracker( + LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); if (ret) { goto end; } /* gid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_GID); + ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_GROUP_ID); if (ret) { goto end; } /* vgid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_VGID); + ret = list_process_attr_tracker( + LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); if (ret) { goto end; } break; case LTTNG_DOMAIN_UST: /* vpid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_VPID); + ret = list_process_attr_tracker( + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); if (ret) { goto end; } /* vuid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_VUID); + ret = list_process_attr_tracker( + LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); if (ret) { goto end; } /* vgid tracker */ - ret = list_tracker_ids(LTTNG_TRACKER_VGID); + ret = list_process_attr_tracker( + LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); if (ret) { goto end; } @@ -1708,6 +1852,7 @@ static int list_trackers(const struct lttng_domain *domain) default: break; } + MSG(); if (lttng_opt_mi) { /* Close trackers element */ ret = mi_lttng_writer_close_element(writer); diff --git a/src/bin/lttng/commands/track-untrack.c b/src/bin/lttng/commands/track-untrack.c index 498e7ed31..d28f8a7e1 100644 --- a/src/bin/lttng/commands/track-untrack.c +++ b/src/bin/lttng/commands/track-untrack.c @@ -1,11 +1,17 @@ /* * Copyright (C) 2011 David Goulet * Copyright (C) 2015 Mathieu Desnoyers + * Copyright (C) 2020 Jérémie Galarneau * * SPDX-License-Identifier: GPL-2.0-only * */ +#include "common/dynamic-buffer.h" +#include "common/tracker.h" +#include "lttng/domain.h" +#include "lttng/lttng-error.h" +#include "lttng/tracker.h" #define _LGPL_SOURCE #include #include @@ -20,574 +26,567 @@ #include +#include #include +#include #include "../command.h" +struct process_attr_command_args { + enum lttng_process_attr process_attr; + /* Present in the user's command. */ + bool requested; + bool all; + struct lttng_dynamic_pointer_array string_args; +}; + enum cmd_type { CMD_TRACK, CMD_UNTRACK, }; -enum tracker_type_state { - STATE_NONE = 0, - STATE_PID, - STATE_VPID, - STATE_UID, - STATE_VUID, - STATE_GID, - STATE_VGID, -}; - -struct opt_type { - int used; - int all; - char *string; -}; - -struct id_list { - size_t nr; - struct lttng_tracker_id **array; -}; - -static char *opt_session_name; -static int opt_kernel; -static int opt_userspace; - -static struct opt_type opt_pid, opt_vpid, opt_uid, opt_vuid, opt_gid, opt_vgid; - -static enum tracker_type_state type_state; - +/* Offset OPT_ values by one since libpopt gives '0' a special meaning. */ enum { - OPT_HELP = 1, + OPT_PID = LTTNG_PROCESS_ATTR_PROCESS_ID + 1, + OPT_VPID = LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID + 1, + OPT_UID = LTTNG_PROCESS_ATTR_USER_ID + 1, + OPT_VUID = LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID + 1, + OPT_GID = LTTNG_PROCESS_ATTR_GROUP_ID + 1, + OPT_VGID = LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID + 1, + OPT_HELP, OPT_LIST_OPTIONS, OPT_SESSION, - OPT_PID, - OPT_VPID, - OPT_UID, - OPT_VUID, - OPT_GID, - OPT_VGID, OPT_ALL, }; +static char *opt_session_name; +static int opt_kernel; +static int opt_userspace; +static char *opt_str_arg; + static struct poptOption long_options[] = { /* { longName, shortName, argInfo, argPtr, value, descrip, argDesc, } */ { "help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0, }, { "session", 's', POPT_ARG_STRING, &opt_session_name, OPT_SESSION, 0, 0, }, { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0, }, { "userspace", 'u', POPT_ARG_VAL, &opt_userspace, 1, 0, 0, }, - { "pid", 'p', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_pid.string, OPT_PID, 0, 0, }, - { "vpid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_vpid.string, OPT_VPID, 0, 0, }, - { "uid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_uid.string, OPT_UID, 0, 0, }, - { "vuid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_vuid.string, OPT_VUID, 0, 0, }, - { "gid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_gid.string, OPT_GID, 0, 0, }, - { "vgid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_vgid.string, OPT_VGID, 0, 0, }, + { "pid", 'p', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_str_arg, OPT_PID, 0, 0, }, + { "vpid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_str_arg, OPT_VPID, 0, 0, }, + { "uid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_str_arg, OPT_UID, 0, 0, }, + { "vuid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_str_arg, OPT_VUID, 0, 0, }, + { "gid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_str_arg, OPT_GID, 0, 0, }, + { "vgid", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_str_arg, OPT_VGID, 0, 0, }, { "all", 'a', POPT_ARG_NONE, 0, OPT_ALL, 0, 0, }, { "list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, 0, 0, }, { 0, 0, 0, 0, 0, 0, 0, }, }; -static struct id_list *alloc_id_list(size_t nr_items) -{ - struct id_list *id_list; - struct lttng_tracker_id **items; - - id_list = zmalloc(sizeof(*id_list)); - if (!id_list) { - goto error; - } - items = zmalloc(nr_items * sizeof(*items)); - if (!items) { - goto error; - } - id_list->nr = nr_items; - id_list->array = items; - return id_list; -error: - free(id_list); - return NULL; -} +static struct process_attr_command_args + process_attr_commands[LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID + 1]; -static void free_id_list(struct id_list *list) +static void process_attr_command_init(struct process_attr_command_args *cmd, + enum lttng_process_attr process_attr) { - size_t nr_items; - int i; - - if (!list) { - return; - } - nr_items = list->nr; - for (i = 0; i < nr_items; i++) { - struct lttng_tracker_id *item = list->array[i]; - lttng_tracker_id_destroy(item); - } - free(list); + cmd->process_attr = process_attr; + cmd->all = false; + lttng_dynamic_pointer_array_init(&cmd->string_args, NULL); } -static int parse_id_string(const char *_id_string, - int all, - struct id_list **_id_list, - enum lttng_tracker_type tracker_type) +static void process_attr_command_fini(struct process_attr_command_args *cmd) { - const char *one_id_str; - char *iter; - int retval = CMD_SUCCESS; - int count = 0; - struct id_list *id_list = NULL; - char *id_string = NULL; - char *endptr; - - if (all && _id_string) { - ERR("An empty ID string is expected with --all"); - retval = CMD_ERROR; - goto error; - } - if (!all && !_id_string) { - ERR("An ID string is expected"); - retval = CMD_ERROR; - goto error; - } - if (all) { - enum lttng_tracker_id_status status; - /* Empty `ID string means all IDs */ - id_list = alloc_id_list(1); - if (!id_list) { - ERR("Out of memory"); - retval = CMD_ERROR; - goto error; - } - - id_list->array[0] = lttng_tracker_id_create(); - if (id_list->array[0] == NULL) { - ERR("Out of memory"); - retval = CMD_ERROR; - goto error; - } - - status = lttng_tracker_id_set_all(id_list->array[0]); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ERR("Invalid value for tracker id"); - retval = CMD_ERROR; - goto error; - } - goto assign; - } - - id_string = strdup(_id_string); - if (!id_string) { - ERR("Out of memory"); - retval = CMD_ERROR; - goto error; - } - - /* Count */ - one_id_str = strtok_r(id_string, ",", &iter); - while (one_id_str != NULL) { - unsigned long v; - - if (isdigit(one_id_str[0])) { - errno = 0; - v = strtoul(one_id_str, &endptr, 10); - if ((v == 0 && errno == EINVAL) || - (v == ULONG_MAX && errno == ERANGE) || - (*one_id_str != '\0' && - *endptr != '\0')) { - ERR("Error parsing ID %s", one_id_str); - retval = CMD_ERROR; - goto error; - } - - if ((long) v > INT_MAX || (int) v < 0) { - ERR("Invalid ID value %ld", (long) v); - retval = CMD_ERROR; - goto error; - } - } - count++; - - /* For next loop */ - one_id_str = strtok_r(NULL, ",", &iter); - } - if (count == 0) { - ERR("Fatal error occurred when parsing pid string"); - retval = CMD_ERROR; - goto error; - } - - free(id_string); - /* Identity of delimiter has been lost in first pass. */ - id_string = strdup(_id_string); - if (!id_string) { - ERR("Out of memory"); - retval = CMD_ERROR; - goto error; - } - - /* Allocate */ - id_list = alloc_id_list(count); - if (!id_list) { - ERR("Out of memory"); - retval = CMD_ERROR; - goto error; - } - - /* Reparse string and populate the id list. */ - count = 0; - one_id_str = strtok_r(id_string, ",", &iter); - while (one_id_str != NULL) { - enum lttng_tracker_id_status status; - struct lttng_tracker_id *item; - item = lttng_tracker_id_create(); - if (item == NULL) { - ERR("Out of memory"); - retval = CMD_ERROR; - goto error; - } - - id_list->array[count++] = item; - if (isdigit(one_id_str[0])) { - unsigned long v; - - v = strtoul(one_id_str, NULL, 10); - status = lttng_tracker_id_set_value(item, (int) v); - if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { - ERR("Invalid value"); - retval = CMD_ERROR; - goto error; - } - } else { - status = lttng_tracker_id_set_string(item, one_id_str); - if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { - ERR("Failed to set ID string"); - retval = CMD_ERROR; - goto error; - } - } - - /* For next loop */ - one_id_str = strtok_r(NULL, ",", &iter); - } - -assign: - /* SUCCESS */ - *_id_list = id_list; - goto end; - -error: - /* ERROR */ - free_id_list(id_list); -end: - free(id_string); - return retval; + lttng_dynamic_pointer_array_reset(&cmd->string_args); } -static const char *get_tracker_str(enum lttng_tracker_type tracker_type) +static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr) { - switch (tracker_type) { - case LTTNG_TRACKER_PID: - return "PID"; - case LTTNG_TRACKER_VPID: - return "VPID"; - case LTTNG_TRACKER_UID: - return "UID"; - case LTTNG_TRACKER_VUID: - return "VUID"; - case LTTNG_TRACKER_GID: - return "GID"; - case LTTNG_TRACKER_VGID: - return "VGID"; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + return "Process ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + return "Virtual process ID"; + case LTTNG_PROCESS_ATTR_USER_ID: + return "User ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + return "Virtual user ID"; + case LTTNG_PROCESS_ATTR_GROUP_ID: + return "Group ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + return "Virtual group ID"; default: - return NULL; + return "Unknown"; } return NULL; } -static int ust_tracker_type_support(enum lttng_tracker_type *tracker_type) +static bool ust_process_attr_supported(enum lttng_process_attr *process_attr) { - int ret; - - switch (*tracker_type) { - case LTTNG_TRACKER_PID: - *tracker_type = LTTNG_TRACKER_VPID; - ret = 0; - break; - case LTTNG_TRACKER_VPID: - case LTTNG_TRACKER_VUID: - case LTTNG_TRACKER_VGID: - ret = 0; - break; - case LTTNG_TRACKER_UID: - case LTTNG_TRACKER_GID: - ERR("The %s tracker is invalid for UST domain.", - get_tracker_str(*tracker_type)); - ret = -1; + bool supported; + + switch (*process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + *process_attr = LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID; + /* fall-through. */ + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + supported = true; break; default: - ret = -1; + ERR("The %s process attribute cannot be tracked in the user space domain.", + lttng_process_attr_to_string(*process_attr)); + supported = false; break; } - - return ret; + return supported; } -static enum cmd_error_code track_untrack_id(enum cmd_type cmd_type, - const char *cmd_str, - const char *session_name, - const char *id_string, - int all, - struct mi_writer *writer, - enum lttng_tracker_type tracker_type) +static const char *get_mi_element_command(enum cmd_type cmd_type) { - int ret, success = 1 , i; - enum cmd_error_code retval = CMD_SUCCESS; - struct id_list *id_list = NULL; - struct lttng_domain dom; - struct lttng_handle *handle = NULL; - int (*cmd_func)(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id); - const char *tracker_str; - switch (cmd_type) { case CMD_TRACK: - cmd_func = lttng_track_id; - break; + return mi_lttng_element_command_track; case CMD_UNTRACK: - cmd_func = lttng_untrack_id; - break; + return mi_lttng_element_command_untrack; default: - ERR("Unknown command"); - retval = CMD_ERROR; - goto end; + abort(); } - memset(&dom, 0, sizeof(dom)); - if (opt_kernel) { - dom.type = LTTNG_DOMAIN_KERNEL; - } else if (opt_userspace) { - dom.type = LTTNG_DOMAIN_UST; - ret = ust_tracker_type_support(&tracker_type); +} + +static enum cmd_error_code run_command_all(enum cmd_type cmd_type, + const char *session_name, + enum lttng_domain_type domain_type, + enum lttng_process_attr process_attr, + struct mi_writer *writer) +{ + struct lttng_process_attr_tracker_handle *tracker_handle = NULL; + const enum lttng_error_code handle_ret_code = + lttng_session_get_tracker_handle(session_name, + domain_type, process_attr, + &tracker_handle); + enum cmd_error_code cmd_ret = CMD_SUCCESS; + enum lttng_process_attr_tracker_handle_status status; + + if (writer) { + const int ret = mi_lttng_all_process_attribute_value( + writer, process_attr, true); if (ret) { - ERR("Invalid parameter"); - retval = CMD_ERROR; + cmd_ret = CMD_FATAL; goto end; } - } else { - /* Checked by the caller. */ - assert(0); - } - tracker_str = get_tracker_str(tracker_type); - if (!tracker_str) { - ERR("Unknown tracker type"); - retval = CMD_ERROR; - goto end; - } - ret = parse_id_string(id_string, all, &id_list, tracker_type); - if (ret != CMD_SUCCESS) { - ERR("Error parsing %s string", tracker_str); - retval = CMD_ERROR; - goto end; } - handle = lttng_create_handle(session_name, &dom); - if (handle == NULL) { - retval = CMD_ERROR; + if (handle_ret_code != LTTNG_OK) { + ERR("Session `%s` does not exist", session_name); + cmd_ret = CMD_FATAL; goto end; } + status = lttng_process_attr_tracker_handle_set_tracking_policy( + tracker_handle, + cmd_type == CMD_TRACK ? + LTTNG_TRACKING_POLICY_INCLUDE_ALL : + LTTNG_TRACKING_POLICY_EXCLUDE_ALL); + switch (status) { + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: + if (cmd_type == CMD_TRACK) { + MSG("%s tracking policy set to `include all`", + get_capitalized_process_attr_str(process_attr)); + } else { + MSG("%s tracking policy set to `exclude all`", + get_capitalized_process_attr_str(process_attr)); + } + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST: + ERR("%s", lttng_strerror(-LTTNG_ERR_SESS_NOT_FOUND)); + break; + default: + ERR("Unknown error encountered while setting tracking policy of %s tracker to `%s`", + lttng_process_attr_to_string(process_attr), + cmd_type == CMD_TRACK ? "include all" : + "exclude all"); + cmd_ret = CMD_FATAL; + break; + } +end: if (writer) { - /* Open tracker_id and targets elements */ - ret = mi_lttng_id_tracker_open(writer, tracker_type); + int ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_success, + cmd_ret == CMD_SUCCESS); + if (ret) { - goto end; + cmd_ret = CMD_FATAL; + } else { + ret = mi_lttng_writer_close_element(writer); + cmd_ret = ret == 0 ? cmd_ret : CMD_FATAL; } } + lttng_process_attr_tracker_handle_destroy(tracker_handle); + return cmd_ret; +} - for (i = 0; i < id_list->nr; i++) { - struct lttng_tracker_id *item = id_list->array[i]; - enum lttng_tracker_id_type type = - lttng_tracker_id_get_type(item); - enum lttng_tracker_id_status status = - LTTNG_TRACKER_ID_STATUS_OK; - int value; - const char *value_string; - - switch (type) { - case LTTNG_ID_ALL: - /* Nothing to check */ - break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_get_value(item, &value); - break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_get_string( - item, &value_string); - break; - default: - retval = CMD_ERROR; - goto end; - } +static enum cmd_error_code run_command_string(enum cmd_type cmd_type, + const char *session_name, + enum lttng_domain_type domain_type, + enum lttng_process_attr process_attr, + const char *_args, + struct mi_writer *writer) +{ + struct lttng_process_attr_tracker_handle *tracker_handle; + const enum lttng_error_code handle_ret_code = + lttng_session_get_tracker_handle(session_name, + domain_type, process_attr, + &tracker_handle); + enum cmd_error_code cmd_ret = CMD_SUCCESS; + const char *one_value_str; + char *args = strdup(_args); + char *iter = args; + bool policy_set = false; + + if (!args) { + ERR("%s", lttng_strerror(-LTTNG_ERR_NOMEM)); + cmd_ret = CMD_FATAL; + goto end; + } - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ERR("Tracker id object is in an invalid state"); - retval = CMD_ERROR; - goto end; - } + if (handle_ret_code != LTTNG_OK) { + ERR("%s", lttng_strerror(-handle_ret_code)); + cmd_ret = CMD_FATAL; + goto end; + } - switch (type) { - case LTTNG_ID_ALL: - DBG("%s all IDs", cmd_str); - break; - case LTTNG_ID_VALUE: - DBG("%s ID %d", cmd_str, value); - break; - case LTTNG_ID_STRING: - DBG("%s ID '%s'", cmd_str, value_string); - break; - default: - retval = CMD_ERROR; - goto end; + while ((one_value_str = strtok_r(iter, ",", &iter)) != NULL) { + const bool is_numerical_argument = isdigit(one_value_str[0]); + enum lttng_process_attr_tracker_handle_status status; + enum lttng_tracking_policy policy; + int ret; + char *prettified_arg; + + if (!policy_set) { + status = lttng_process_attr_tracker_handle_get_tracking_policy( + tracker_handle, &policy); + if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + break; + } + + if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) { + status = lttng_process_attr_tracker_handle_set_tracking_policy( + tracker_handle, + LTTNG_TRACKING_POLICY_INCLUDE_SET); + if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + break; + } + } + policy_set = true; } - ret = cmd_func(handle, tracker_type, item); - if (ret) { - const char *msg = NULL; + if (is_numerical_argument) { + const unsigned long one_value_int = + strtoul(one_value_str, NULL, 10); + + if (writer) { + const int ret = mi_lttng_integral_process_attribute_value( + writer, process_attr, + (int64_t) one_value_int, true); + if (ret) { + cmd_ret = CMD_FATAL; + goto end; + } + } - switch (-ret) { - case LTTNG_ERR_ID_TRACKED: - msg = "already tracked"; - success = 1; - retval = CMD_SUCCESS; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_process_id_tracker_handle_add_pid( + tracker_handle, + (pid_t) one_value_int) : + lttng_process_attr_process_id_tracker_handle_remove_pid( + tracker_handle, + (pid_t) one_value_int); break; - case LTTNG_ERR_ID_NOT_TRACKED: - msg = "already not tracked"; - success = 1; - retval = CMD_SUCCESS; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_virtual_process_id_tracker_handle_add_pid( + tracker_handle, + (pid_t) one_value_int) : + lttng_process_attr_virtual_process_id_tracker_handle_remove_pid( + tracker_handle, + (pid_t) one_value_int); break; - default: - ERR("%s", lttng_strerror(ret)); - success = 0; - retval = CMD_ERROR; + case LTTNG_PROCESS_ATTR_USER_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_user_id_tracker_handle_add_uid( + tracker_handle, + (uid_t) one_value_int) : + lttng_process_attr_user_id_tracker_handle_remove_uid( + tracker_handle, + (uid_t) one_value_int); + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_virtual_user_id_tracker_handle_add_uid( + tracker_handle, + (uid_t) one_value_int) : + lttng_process_attr_virtual_user_id_tracker_handle_remove_uid( + tracker_handle, + (uid_t) one_value_int); + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_group_id_tracker_handle_add_gid( + tracker_handle, + (gid_t) one_value_int) : + lttng_process_attr_group_id_tracker_handle_remove_gid( + tracker_handle, + (gid_t) one_value_int); break; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_virtual_group_id_tracker_handle_add_gid( + tracker_handle, + (gid_t) one_value_int) : + lttng_process_attr_virtual_group_id_tracker_handle_remove_gid( + tracker_handle, + (gid_t) one_value_int); + break; + default: + abort(); } - if (msg) { - switch (type) { - case LTTNG_ID_ALL: - WARN("All %ss %s in session %s", - tracker_str, msg, - session_name); - break; - case LTTNG_ID_VALUE: - WARN("%s %i %s in session %s", - tracker_str, value, msg, - session_name); - break; - case LTTNG_ID_STRING: - WARN("%s '%s' %s in session %s", - tracker_str, - value_string, msg, - session_name); - break; - default: - retval = CMD_ERROR; + + } else { + if (writer) { + const int ret = mi_lttng_string_process_attribute_value( + writer, process_attr, + one_value_str, true); + if (ret) { + cmd_ret = CMD_FATAL; goto end; } } - } else { - switch (type) { - case LTTNG_ID_ALL: - MSG("All %ss %sed in session %s", tracker_str, - cmd_str, session_name); + + switch (process_attr) { + case LTTNG_PROCESS_ATTR_USER_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_user_id_tracker_handle_add_user_name( + tracker_handle, + one_value_str) : + lttng_process_attr_user_id_tracker_handle_remove_user_name( + tracker_handle, + one_value_str); break; - case LTTNG_ID_VALUE: - MSG("%s %i %sed in session %s", tracker_str, - value, cmd_str, session_name); + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_virtual_user_id_tracker_handle_add_user_name( + tracker_handle, + one_value_str) : + lttng_process_attr_virtual_user_id_tracker_handle_remove_user_name( + tracker_handle, + one_value_str); break; - case LTTNG_ID_STRING: - MSG("%s '%s' %sed in session %s", tracker_str, - value_string, cmd_str, - session_name); + case LTTNG_PROCESS_ATTR_GROUP_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_group_id_tracker_handle_add_group_name( + tracker_handle, + one_value_str) : + lttng_process_attr_group_id_tracker_handle_remove_group_name( + tracker_handle, + one_value_str); + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + status = cmd_type == CMD_TRACK ? + lttng_process_attr_virtual_group_id_tracker_handle_add_group_name( + tracker_handle, + one_value_str) : + lttng_process_attr_virtual_group_id_tracker_handle_remove_group_name( + tracker_handle, + one_value_str); break; default: - retval = CMD_ERROR; + ERR("%s is not a valid %s value; expected an integer", + one_value_str, + lttng_process_attr_to_string( + process_attr)); + cmd_ret = CMD_FATAL; goto end; } - success = 1; } - /* Mi */ - if (writer) { - ret = mi_lttng_id_target(writer, tracker_type, item, 1); - if (ret) { - retval = CMD_ERROR; - goto end; - } + ret = asprintf(&prettified_arg, + is_numerical_argument ? "%s" : "`%s`", + one_value_str); + if (ret < 0) { + PERROR("Failed to format argument `%s`", one_value_str); + cmd_ret = CMD_FATAL; + goto end; + } - ret = mi_lttng_writer_write_element_bool(writer, - mi_lttng_element_success, success); - if (ret) { - retval = CMD_ERROR; - goto end; + switch (status) { + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: + if (cmd_type == CMD_TRACK) { + MSG("Added %s to the %s tracker inclusion set", + one_value_str, + lttng_process_attr_to_string( + process_attr)); + } else { + MSG("Removed %s from the %s tracker inclusion set", + one_value_str, + lttng_process_attr_to_string( + process_attr)); } + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST: + ERR("Session `%s` not found", session_name); + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS: + WARN("%s is already in the %s inclusion set", + prettified_arg, + lttng_process_attr_to_string( + process_attr)); + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING: + WARN("%s is not in the %s the inclusion set", + prettified_arg, + lttng_process_attr_to_string( + process_attr)); + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND: + ERR("User %s was not found", prettified_arg); + cmd_ret = CMD_ERROR; + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND: + ERR("Group %s was not found", prettified_arg); + cmd_ret = CMD_ERROR; + break; + default: + ERR("Unknown error encountered while %s %s %s %s tracker's inclusion set", + cmd_type == CMD_TRACK ? "adding" : + "removing", + lttng_process_attr_to_string( + process_attr), + prettified_arg, + cmd_type == CMD_TRACK ? "to" : "from"); + cmd_ret = CMD_FATAL; + break; + } + free(prettified_arg); + + if (writer) { + int ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_success, + cmd_ret == CMD_SUCCESS); - ret = mi_lttng_writer_close_element(writer); if (ret) { - retval = CMD_ERROR; - goto end; + cmd_ret = CMD_FATAL; + } else { + ret = mi_lttng_writer_close_element(writer); + cmd_ret = ret == 0 ? cmd_ret : CMD_FATAL; } } } +end: + free(args); + lttng_process_attr_tracker_handle_destroy(tracker_handle); + return cmd_ret; +} + +static enum cmd_error_code run_command(enum cmd_type cmd_type, + const char *session_name, + const struct process_attr_command_args *command_args, + struct mi_writer *writer) +{ + const enum lttng_domain_type domain_type = + opt_kernel ? LTTNG_DOMAIN_KERNEL : LTTNG_DOMAIN_UST; + enum cmd_error_code cmd_ret = CMD_SUCCESS; + unsigned int i; + const unsigned int string_arg_count = + lttng_dynamic_pointer_array_get_count( + &command_args->string_args); + enum lttng_process_attr process_attr = command_args->process_attr; + + if (opt_userspace) { + /* + * Check that this process attribute can be tracked + * in the user space domain. Backward-compatibility + * changes are be applied to process_attr as needed. + */ + if (!ust_process_attr_supported(&process_attr)) { + cmd_ret = CMD_ERROR; + goto end; + } + } if (writer) { - /* Close targets and tracker_id elements */ - ret = mi_lttng_close_multi_element(writer, 2); + /* Open tracker and trackers elements */ + const int ret = mi_lttng_process_attribute_tracker_open( + writer, process_attr); if (ret) { - retval = CMD_ERROR; + cmd_ret = CMD_FATAL; goto end; } } -end: - if (handle) { - lttng_destroy_handle(handle); - } - free_id_list(id_list); - return retval; -} + if (command_args->all) { + cmd_ret = run_command_all(cmd_type, session_name, domain_type, + process_attr, writer); + } else { + bool error_occurred = false; -static -const char *get_mi_element_command(enum cmd_type cmd_type) -{ - switch (cmd_type) { - case CMD_TRACK: - return mi_lttng_element_command_track; - case CMD_UNTRACK: - return mi_lttng_element_command_untrack; - default: - return NULL; + for (i = 0; i < string_arg_count; i++) { + const char *arg = lttng_dynamic_pointer_array_get_pointer( + &command_args->string_args, i); + + cmd_ret = run_command_string(cmd_type, session_name, + domain_type, process_attr, arg, writer); + if (cmd_ret != CMD_SUCCESS) { + error_occurred = true; + if (cmd_ret == CMD_FATAL) { + break; + } + goto end; + } + } + if (error_occurred) { + cmd_ret = CMD_ERROR; + } } -} -static void print_err_duplicate(const char *type) -{ - ERR("The --%s option can only be used once. A list of comma-separated values can be specified.", - type); + if (writer) { + /* Close tracker and trackers elements */ + const int ret = mi_lttng_close_multi_element( + writer, 2); + if (ret) { + cmd_ret = CMD_FATAL; + goto end; + } + } +end: + return cmd_ret; } /* * Add/remove tracker to/from session. */ -static -int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, - int argc, const char **argv, const char *help_msg) +static int cmd_track_untrack(enum cmd_type cmd_type, + int argc, + const char **argv, + const char *help_msg) { - int opt, ret = 0, success = 1; - bool opt_all_present = false; + int opt, ret = 0; + bool sub_command_failed = false; + bool opt_all = false; + unsigned int selected_process_attr_tracker_count = 0; + const unsigned int command_count = + sizeof(process_attr_commands) / + sizeof(struct process_attr_command_args); enum cmd_error_code command_ret = CMD_SUCCESS; static poptContext pc; char *session_name = NULL; const char *leftover = NULL; struct mi_writer *writer = NULL; + size_t i; + + for (i = 0; i < command_count; i++) { + process_attr_command_init(&process_attr_commands[i], i); + } if (argc < 1) { command_ret = CMD_ERROR; @@ -608,61 +607,29 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, case OPT_SESSION: break; case OPT_PID: - if (opt_pid.used) { - print_err_duplicate("pid"); - command_ret = CMD_ERROR; - goto end; - } - opt_pid.used = 1; - type_state = STATE_PID; - break; case OPT_VPID: - if (opt_vpid.used) { - print_err_duplicate("vpid"); - command_ret = CMD_ERROR; - goto end; - } - opt_vpid.used = 1; - type_state = STATE_VPID; - break; case OPT_UID: - if (opt_uid.used) { - print_err_duplicate("uid"); - command_ret = CMD_ERROR; - goto end; - } - opt_uid.used = 1; - type_state = STATE_UID; - break; case OPT_VUID: - if (opt_vuid.used) { - print_err_duplicate("vuid"); - command_ret = CMD_ERROR; - goto end; - } - opt_vuid.used = 1; - type_state = STATE_VUID; - break; case OPT_GID: - if (opt_gid.used) { - print_err_duplicate("gid"); - command_ret = CMD_ERROR; - goto end; - } - opt_gid.used = 1; - type_state = STATE_GID; - break; case OPT_VGID: - if (opt_vgid.used) { - print_err_duplicate("vgid"); + /* See OPT_ enum declaration comment. */ + opt--; + selected_process_attr_tracker_count++; + process_attr_commands[opt].requested = true; + if (!opt_str_arg) { + continue; + } + ret = lttng_dynamic_pointer_array_add_pointer( + &process_attr_commands[opt].string_args, + opt_str_arg); + if (ret) { + ERR("Allocation failed while parsing command arguments"); command_ret = CMD_ERROR; goto end; } - opt_vgid.used = 1; - type_state = STATE_VGID; break; case OPT_ALL: - opt_all_present = true; + opt_all = true; break; default: command_ret = CMD_UNDEFINED; @@ -677,33 +644,44 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, goto end; } - /* - * If the `--all` option is present set the appropriate tracker's `all` - * field. - */ - if (opt_all_present) { - switch (type_state) { - case STATE_PID: - opt_pid.all = 1; - break; - case STATE_VPID: - opt_vpid.all = 1; - break; - case STATE_UID: - opt_uid.all = 1; - break; - case STATE_VUID: - opt_vuid.all = 1; - break; - case STATE_GID: - opt_gid.all = 1; - break; - case STATE_VGID: - opt_vgid.all = 1; - break; - default: - command_ret = CMD_ERROR; - goto end; + if (selected_process_attr_tracker_count == 0) { + ERR("At least one process attribute must be specified"); + command_ret = CMD_ERROR; + goto end; + } + if (opt_all) { + /* + * Only one process attribute tracker was specified; find it + * and set it in 'all' mode. + */ + for (i = 0; i < command_count; i++) { + if (!process_attr_commands[i].requested) { + continue; + } + process_attr_commands[i].all = true; + if (lttng_dynamic_pointer_array_get_count( + &process_attr_commands[i] + .string_args)) { + ERR("The --all option cannot be used with a list of process attribute values"); + command_ret = CMD_ERROR; + goto end; + } + } + } else { + for (i = 0; i < command_count; i++) { + if (!process_attr_commands[i].requested) { + continue; + } + if (lttng_dynamic_pointer_array_get_count( + &process_attr_commands[i] + .string_args) == 0) { + ERR("No process attribute value specified for %s tracker", + get_capitalized_process_attr_str( + process_attr_commands[i] + .process_attr)); + command_ret = CMD_ERROR; + goto end; + } } } @@ -756,52 +734,18 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, } } - if (opt_pid.used) { - command_ret = track_untrack_id(cmd_type, cmd_str, session_name, - opt_pid.string, opt_pid.all, writer, - LTTNG_TRACKER_PID); - if (command_ret != CMD_SUCCESS) { - success = 0; - } - } - if (opt_vpid.used) { - command_ret = track_untrack_id(cmd_type, cmd_str, session_name, - opt_vpid.string, opt_vpid.all, writer, - LTTNG_TRACKER_VPID); - if (command_ret != CMD_SUCCESS) { - success = 0; - } - } - if (opt_uid.used) { - command_ret = track_untrack_id(cmd_type, cmd_str, session_name, - opt_uid.string, opt_uid.all, writer, - LTTNG_TRACKER_UID); - if (command_ret != CMD_SUCCESS) { - success = 0; - } - } - if (opt_vuid.used) { - command_ret = track_untrack_id(cmd_type, cmd_str, session_name, - opt_vuid.string, opt_vuid.all, writer, - LTTNG_TRACKER_VUID); - if (command_ret != CMD_SUCCESS) { - success = 0; + /* Execute sub-commands. */ + for (i = 0; i < command_count; i++) { + if (!process_attr_commands[i].requested) { + continue; } - } - if (opt_gid.used) { - command_ret = track_untrack_id(cmd_type, cmd_str, session_name, - opt_gid.string, opt_gid.all, writer, - LTTNG_TRACKER_GID); - if (command_ret != CMD_SUCCESS) { - success = 0; - } - } - if (opt_vgid.used) { - command_ret = track_untrack_id(cmd_type, cmd_str, session_name, - opt_vgid.string, opt_vgid.all, writer, - LTTNG_TRACKER_VGID); + command_ret = run_command(cmd_type, session_name, + &process_attr_commands[i], writer); if (command_ret != CMD_SUCCESS) { - success = 0; + sub_command_failed = true; + if (command_ret == CMD_FATAL) { + break; + } } } @@ -816,7 +760,8 @@ int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, /* Success ? */ ret = mi_lttng_writer_write_element_bool(writer, - mi_lttng_element_command_success, success); + mi_lttng_element_command_success, + !sub_command_failed); if (ret) { command_ret = CMD_ERROR; goto end; @@ -841,6 +786,10 @@ end: command_ret = CMD_ERROR; } + for (i = 0; i < command_count; i++) { + process_attr_command_fini(&process_attr_commands[i]); + } + poptFreeContext(pc); return (int) command_ret; } @@ -855,7 +804,7 @@ int cmd_track(int argc, const char **argv) #endif ; - return cmd_track_untrack(CMD_TRACK, "track", argc, argv, help_msg); + return cmd_track_untrack(CMD_TRACK, argc, argv, help_msg); } int cmd_untrack(int argc, const char **argv) @@ -868,5 +817,5 @@ int cmd_untrack(int argc, const char **argv) #endif ; - return cmd_track_untrack(CMD_UNTRACK, "untrack", argc, argv, help_msg); + return cmd_track_untrack(CMD_UNTRACK, argc, argv, help_msg); } diff --git a/src/common/Makefile.am b/src/common/Makefile.am index a50123989..1c9c8e4f0 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -64,7 +64,7 @@ libcommon_la_SOURCES = \ userspace-probe.c \ utils.c utils.h \ uuid.c uuid.h \ - tracker.c \ + tracker.c tracker.h \ waiter.c waiter.h \ fs-handle.h fs-handle-internal.h fs-handle.c diff --git a/src/common/config/config-session-abi.h b/src/common/config/config-session-abi.h index eeb988479..41f675041 100644 --- a/src/common/config/config-session-abi.h +++ b/src/common/config/config-session-abi.h @@ -75,26 +75,26 @@ extern const char * const config_element_control_uri; extern const char * const config_element_data_uri; extern const char * const config_element_max_size; extern const char * const config_element_pid; -extern const char * const config_element_id; +extern const char * const config_element_process_attr_id; extern const char * const config_element_pids; extern const char * const config_element_name; extern const char * const config_element_shared_memory_path; -extern const char * const config_element_pid_tracker; -extern const char * const config_element_vpid_tracker; -extern const char * const config_element_uid_tracker; -extern const char * const config_element_vuid_tracker; -extern const char * const config_element_gid_tracker; -extern const char * const config_element_vgid_tracker; -extern const char * const config_element_trackers; -extern const char * const config_element_targets; -extern const char * const config_element_target_type; -extern const char * const config_element_target_pid; -extern const char * const config_element_target_vpid; -extern const char * const config_element_target_uid; -extern const char * const config_element_target_vuid; -extern const char * const config_element_target_gid; -extern const char * const config_element_target_vgid; -extern const char * const config_element_tracker_type; +extern const char * const config_element_process_attr_tracker_pid; +extern const char * const config_element_process_attr_tracker_vpid; +extern const char * const config_element_process_attr_tracker_uid; +extern const char * const config_element_process_attr_tracker_vuid; +extern const char * const config_element_process_attr_tracker_gid; +extern const char * const config_element_process_attr_tracker_vgid; +extern const char * const config_element_process_attr_trackers; +extern const char * const config_element_process_attr_values; +extern const char * const config_element_process_attr_value_type; +extern const char * const config_element_process_attr_pid_value; +extern const char * const config_element_process_attr_vpid_value; +extern const char * const config_element_process_attr_uid_value; +extern const char * const config_element_process_attr_vuid_value; +extern const char * const config_element_process_attr_gid_value; +extern const char * const config_element_process_attr_vgid_value; +extern const char * const config_element_process_attr_tracker_type; extern const char * const config_element_rotation_timer_interval; extern const char * const config_element_rotation_size; extern const char * const config_element_rotation_schedule; diff --git a/src/common/config/session-config.c b/src/common/config/session-config.c index 35c5aeef9..c7f471a1c 100644 --- a/src/common/config/session-config.c +++ b/src/common/config/session-config.c @@ -5,6 +5,7 @@ * */ +#include "lttng/tracker.h" #define _LGPL_SOURCE #include #include @@ -132,25 +133,26 @@ const char * const config_element_control_uri = "control_uri"; const char * const config_element_data_uri = "data_uri"; const char * const config_element_max_size = "max_size"; const char * const config_element_pid = "pid"; -LTTNG_HIDDEN const char * const config_element_id = "id"; const char * const config_element_pids = "pids"; const char * const config_element_shared_memory_path = "shared_memory_path"; -const char * const config_element_pid_tracker = "pid_tracker"; -LTTNG_HIDDEN const char * const config_element_vpid_tracker = "vpid_tracker"; -LTTNG_HIDDEN const char * const config_element_uid_tracker = "uid_tracker"; -LTTNG_HIDDEN const char * const config_element_vuid_tracker = "vuid_tracker"; -LTTNG_HIDDEN const char * const config_element_gid_tracker = "gid_tracker"; -LTTNG_HIDDEN const char * const config_element_vgid_tracker = "vgid_tracker"; -const char * const config_element_trackers = "trackers"; -const char * const config_element_targets = "targets"; -LTTNG_HIDDEN const char * const config_element_target_type = "target_type"; -const char * const config_element_target_pid = "pid_target"; -LTTNG_HIDDEN const char * const config_element_target_vpid = "vpid_target"; -LTTNG_HIDDEN const char * const config_element_target_uid = "uid_target"; -LTTNG_HIDDEN const char * const config_element_target_vuid = "vuid_target"; -LTTNG_HIDDEN const char * const config_element_target_gid = "gid_target"; -LTTNG_HIDDEN const char * const config_element_target_vgid = "vgid_target"; -LTTNG_HIDDEN const char * const config_element_tracker_type = "tracker_type"; + +LTTNG_HIDDEN const char * const config_element_process_attr_id = "id"; +LTTNG_HIDDEN const char * const config_element_process_attr_tracker_pid = "pid_process_attr_tracker"; +LTTNG_HIDDEN const char * const config_element_process_attr_tracker_vpid = "vpid_process_attr_tracker"; +LTTNG_HIDDEN const char * const config_element_process_attr_tracker_uid = "uid_process_attr_tracker"; +LTTNG_HIDDEN const char * const config_element_process_attr_tracker_vuid = "vuid_process_attr_tracker"; +LTTNG_HIDDEN const char * const config_element_process_attr_tracker_gid = "gid_process_attr_tracker"; +LTTNG_HIDDEN const char * const config_element_process_attr_tracker_vgid = "vgid_process_attr_tracker"; +LTTNG_HIDDEN const char * const config_element_process_attr_trackers = "process_attr_trackers"; +LTTNG_HIDDEN const char * const config_element_process_attr_values = "process_attr_values"; +LTTNG_HIDDEN const char * const config_element_process_attr_value_type = "process_attr_value_type"; +LTTNG_HIDDEN const char * const config_element_process_attr_pid_value = "pid"; +LTTNG_HIDDEN const char * const config_element_process_attr_vpid_value = "vpid"; +LTTNG_HIDDEN const char * const config_element_process_attr_uid_value = "uid"; +LTTNG_HIDDEN const char * const config_element_process_attr_vuid_value = "vuid"; +LTTNG_HIDDEN const char * const config_element_process_attr_gid_value = "gid"; +LTTNG_HIDDEN const char * const config_element_process_attr_vgid_value = "vgid"; +LTTNG_HIDDEN const char * const config_element_process_attr_tracker_type = "process_attr_tracker_type"; LTTNG_HIDDEN const char * const config_element_rotation_schedules = "rotation_schedules"; LTTNG_HIDDEN const char * const config_element_rotation_schedule_periodic = "periodic"; @@ -2665,56 +2667,56 @@ end: return ret; } -static int get_tracker_elements(enum lttng_tracker_type tracker_type, +static int get_tracker_elements(enum lttng_process_attr process_attr, const char **element_id_tracker, - const char **element_target_id, - const char **element_id, - const char **element_id_alias, + const char **element_value_type, + const char **element_value, + const char **element_value_alias, const char **element_name) { int ret = 0; - switch (tracker_type) { - case LTTNG_TRACKER_PID: - *element_id_tracker = config_element_pid_tracker; - *element_target_id = config_element_target_pid; - *element_id = config_element_id; - *element_id_alias = config_element_pid; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + *element_id_tracker = config_element_process_attr_tracker_pid; + *element_value_type = config_element_process_attr_pid_value; + *element_value = config_element_process_attr_id; + *element_value_alias = config_element_process_attr_id; *element_name = NULL; break; - case LTTNG_TRACKER_VPID: - *element_id_tracker = config_element_vpid_tracker; - *element_target_id = config_element_target_vpid; - *element_id = config_element_id; - *element_id_alias = NULL; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + *element_id_tracker = config_element_process_attr_tracker_vpid; + *element_value_type = config_element_process_attr_vpid_value; + *element_value = config_element_process_attr_id; + *element_value_alias = NULL; *element_name = NULL; break; - case LTTNG_TRACKER_UID: - *element_id_tracker = config_element_uid_tracker; - *element_target_id = config_element_target_uid; - *element_id = config_element_id; - *element_id_alias = NULL; + case LTTNG_PROCESS_ATTR_USER_ID: + *element_id_tracker = config_element_process_attr_tracker_uid; + *element_value_type = config_element_process_attr_uid_value; + *element_value = config_element_process_attr_id; + *element_value_alias = NULL; *element_name = config_element_name; break; - case LTTNG_TRACKER_VUID: - *element_id_tracker = config_element_vuid_tracker; - *element_target_id = config_element_target_vuid; - *element_id = config_element_id; - *element_id_alias = NULL; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + *element_id_tracker = config_element_process_attr_tracker_vuid; + *element_value_type = config_element_process_attr_vuid_value; + *element_value = config_element_process_attr_id; + *element_value_alias = NULL; *element_name = config_element_name; break; - case LTTNG_TRACKER_GID: - *element_id_tracker = config_element_gid_tracker; - *element_target_id = config_element_target_gid; - *element_id = config_element_id; - *element_id_alias = NULL; + case LTTNG_PROCESS_ATTR_GROUP_ID: + *element_id_tracker = config_element_process_attr_tracker_gid; + *element_value_type = config_element_process_attr_gid_value; + *element_value = config_element_process_attr_id; + *element_value_alias = NULL; *element_name = config_element_name; break; - case LTTNG_TRACKER_VGID: - *element_id_tracker = config_element_vgid_tracker; - *element_target_id = config_element_target_vgid; - *element_id = config_element_id; - *element_id_alias = NULL; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + *element_id_tracker = config_element_process_attr_tracker_vgid; + *element_value_type = config_element_process_attr_vgid_value; + *element_value = config_element_process_attr_id; + *element_value_alias = NULL; *element_name = config_element_name; break; default: @@ -2725,9 +2727,9 @@ static int get_tracker_elements(enum lttng_tracker_type tracker_type, static int process_id_tracker_node(xmlNodePtr id_tracker_node, struct lttng_handle *handle, - enum lttng_tracker_type tracker_type) + enum lttng_process_attr process_attr) { - int ret = 0, child; + int ret = 0, child_count; xmlNodePtr targets_node = NULL; xmlNodePtr node; const char *element_id_tracker; @@ -2735,23 +2737,33 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, const char *element_id; const char *element_id_alias; const char *element_name; - enum lttng_tracker_id_status status; + enum lttng_error_code tracker_handle_ret_code; + struct lttng_process_attr_tracker_handle *tracker_handle = NULL; + enum lttng_process_attr_tracker_handle_status status; assert(handle); assert(id_tracker_node); - ret = get_tracker_elements(tracker_type, &element_id_tracker, + tracker_handle_ret_code = lttng_session_get_tracker_handle( + handle->session_name, handle->domain.type, process_attr, + &tracker_handle); + if (tracker_handle_ret_code != LTTNG_OK) { + ret = LTTNG_ERR_INVALID; + goto end; + } + + ret = get_tracker_elements(process_attr, &element_id_tracker, &element_target_id, &element_id, &element_id_alias, &element_name); if (ret) { - return ret; + goto end; } /* get the targets node */ for (node = xmlFirstElementChild(id_tracker_node); node; node = xmlNextElementSibling(node)) { if (!strcmp((const char *) node->name, - config_element_targets)) { + config_element_process_attr_values)) { targets_node = node; break; } @@ -2763,27 +2775,17 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, } /* Go through all id target node */ - child = xmlChildElementCount(targets_node); - if (child == 0) { - struct lttng_tracker_id *tracker_id = NULL; - tracker_id = lttng_tracker_id_create(); - if (tracker_id == NULL) { - ret = LTTNG_ERR_NOMEM; - goto end; - } - status = lttng_tracker_id_set_all(tracker_id); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = LTTNG_ERR_INVALID; - goto end; - } - - /* The session is explicitly set to target nothing. */ - ret = lttng_untrack_id(handle, tracker_type, tracker_id); - lttng_tracker_id_destroy(tracker_id); - if (ret) { - goto end; - } + child_count = xmlChildElementCount(targets_node); + status = lttng_process_attr_tracker_handle_set_tracking_policy( + tracker_handle, + child_count == 0 ? LTTNG_TRACKING_POLICY_EXCLUDE_ALL : + LTTNG_TRACKING_POLICY_INCLUDE_SET); + if (status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + ret = LTTNG_ERR_UNK; + goto end; } + + /* Add all tracked values. */ for (node = xmlFirstElementChild(targets_node); node; node = xmlNextElementSibling(node)) { xmlNodePtr id_target_node = node; @@ -2796,10 +2798,8 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, !strcmp((const char *) node->name, element_id_alias))) { int64_t id; - xmlChar *content = NULL; - struct lttng_tracker_id *tracker_id = NULL; + xmlChar *content = xmlNodeGetContent(node); - content = xmlNodeGetContent(node); if (!content) { ret = LTTNG_ERR_LOAD_INVALID_CONFIG; goto end; @@ -2812,65 +2812,103 @@ static int process_id_tracker_node(xmlNodePtr id_tracker_node, goto end; } - tracker_id = lttng_tracker_id_create(); - if (tracker_id == NULL) { - ret = LTTNG_ERR_NOMEM; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + status = lttng_process_attr_process_id_tracker_handle_add_pid( + tracker_handle, + (pid_t) id); + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + status = lttng_process_attr_virtual_process_id_tracker_handle_add_pid( + tracker_handle, + (pid_t) id); + break; + case LTTNG_PROCESS_ATTR_USER_ID: + status = lttng_process_attr_user_id_tracker_handle_add_uid( + tracker_handle, + (uid_t) id); + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + status = lttng_process_attr_virtual_user_id_tracker_handle_add_uid( + tracker_handle, + (uid_t) id); + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + status = lttng_process_attr_group_id_tracker_handle_add_gid( + tracker_handle, + (gid_t) id); + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + status = lttng_process_attr_virtual_group_id_tracker_handle_add_gid( + tracker_handle, + (gid_t) id); + break; + default: + ret = LTTNG_ERR_INVALID; goto end; } + } else if (element_name && + !strcmp((const char *) node->name, + element_name)) { + xmlChar *content = xmlNodeGetContent(node); - status = lttng_tracker_id_set_value( - tracker_id, id); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - lttng_tracker_id_destroy(tracker_id); - ret = LTTNG_ERR_LOAD_INVALID_CONFIG; - goto end; - } - - ret = lttng_track_id(handle, tracker_type, - tracker_id); - lttng_tracker_id_destroy(tracker_id); - if (ret) { - goto end; - } - } - if (element_name && !strcmp((const char *) node->name, - element_name)) { - xmlChar *content = NULL; - struct lttng_tracker_id *tracker_id = NULL; - - content = xmlNodeGetContent(node); if (!content) { ret = LTTNG_ERR_LOAD_INVALID_CONFIG; goto end; } - tracker_id = lttng_tracker_id_create(); - if (tracker_id == NULL) { - ret = LTTNG_ERR_NOMEM; - goto end; - } - - status = lttng_tracker_id_set_string(tracker_id, - (const char *) content); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - lttng_tracker_id_destroy(tracker_id); - ret = LTTNG_ERR_LOAD_INVALID_CONFIG; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_USER_ID: + status = lttng_process_attr_user_id_tracker_handle_add_user_name( + tracker_handle, + (const char *) content); + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + status = lttng_process_attr_virtual_user_id_tracker_handle_add_user_name( + tracker_handle, + (const char *) content); + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + status = lttng_process_attr_group_id_tracker_handle_add_group_name( + tracker_handle, + (const char *) content); + break; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + status = lttng_process_attr_virtual_group_id_tracker_handle_add_group_name( + tracker_handle, + (const char *) content); + break; + default: + free(content); + ret = LTTNG_ERR_INVALID; goto end; } - - ret = lttng_track_id(handle, tracker_type, - tracker_id); - lttng_tracker_id_destroy(tracker_id); free(content); - if (ret) { - goto end; - } + } + switch (status) { + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: + continue; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID: + ret = LTTNG_ERR_INVALID; + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS: + ret = LTTNG_ERR_PROCESS_ATTR_EXISTS; + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING: + ret = LTTNG_ERR_PROCESS_ATTR_MISSING; + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR: + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR: + default: + ret = LTTNG_ERR_UNK; + goto end; } } node = id_target_node; } end: + lttng_process_attr_tracker_handle_destroy(tracker_handle); return ret; } @@ -2989,7 +3027,7 @@ int process_domain_node(xmlNodePtr domain_node, const char *session_name) for (node = xmlFirstElementChild(domain_node); node; node = xmlNextElementSibling(node)) { if (!strcmp((const char *) node->name, - config_element_trackers)) { + config_element_process_attr_trackers)) { trackers_node = node; break; } @@ -3002,55 +3040,55 @@ int process_domain_node(xmlNodePtr domain_node, const char *session_name) for (node = xmlFirstElementChild(trackers_node); node; node = xmlNextElementSibling(node)) { if (!strcmp((const char *) node->name, - config_element_pid_tracker)) { + config_element_process_attr_tracker_pid)) { pid_tracker_node = node; ret = process_id_tracker_node(pid_tracker_node, handle, - LTTNG_TRACKER_PID); + LTTNG_PROCESS_ATTR_PROCESS_ID); if (ret) { goto end; } } if (!strcmp((const char *) node->name, - config_element_vpid_tracker)) { + config_element_process_attr_tracker_vpid)) { vpid_tracker_node = node; ret = process_id_tracker_node(vpid_tracker_node, handle, - LTTNG_TRACKER_VPID); + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID); if (ret) { goto end; } } if (!strcmp((const char *) node->name, - config_element_uid_tracker)) { + config_element_process_attr_tracker_uid)) { uid_tracker_node = node; ret = process_id_tracker_node(uid_tracker_node, handle, - LTTNG_TRACKER_UID); + LTTNG_PROCESS_ATTR_USER_ID); if (ret) { goto end; } } if (!strcmp((const char *) node->name, - config_element_vuid_tracker)) { + config_element_process_attr_tracker_vuid)) { vuid_tracker_node = node; ret = process_id_tracker_node(vuid_tracker_node, handle, - LTTNG_TRACKER_VUID); + LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID); if (ret) { goto end; } } if (!strcmp((const char *) node->name, - config_element_gid_tracker)) { + config_element_process_attr_tracker_gid)) { gid_tracker_node = node; ret = process_id_tracker_node(gid_tracker_node, handle, - LTTNG_TRACKER_GID); + LTTNG_PROCESS_ATTR_GROUP_ID); if (ret) { goto end; } } if (!strcmp((const char *) node->name, - config_element_vgid_tracker)) { + config_element_process_attr_tracker_vgid)) { vgid_tracker_node = node; ret = process_id_tracker_node(vgid_tracker_node, handle, - LTTNG_TRACKER_VGID); + LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID); if (ret) { goto end; } diff --git a/src/common/config/session.xsd b/src/common/config/session.xsd index cd752fab4..6f3a5d8af 100644 --- a/src/common/config/session.xsd +++ b/src/common/config/session.xsd @@ -254,154 +254,153 @@ by its signed 32-bit representation when converted to msec. - + - - - + + - + - - + + - + - + - - + + - + - - + + - + - + - - + + - + - - + + - + - + - - + + - + - - + + - + - + - - + + - + - - + + - + - + - - + + - + - - + + - + - + - - - - - - + + + + + + - + - + diff --git a/src/common/error.c b/src/common/error.c index ed81b8b45..70063e504 100644 --- a/src/common/error.c +++ b/src/common/error.c @@ -169,8 +169,8 @@ static const char *error_string_array[] = { [ ERROR_INDEX(LTTNG_ERR_MI_NOT_IMPLEMENTED) ] = "Mi feature not implemented", [ ERROR_INDEX(LTTNG_ERR_INVALID_EVENT_NAME) ] = "Invalid event name", [ ERROR_INDEX(LTTNG_ERR_INVALID_CHANNEL_NAME) ] = "Invalid channel name", - [ ERROR_INDEX(LTTNG_ERR_ID_TRACKED) ] = "ID already tracked", - [ ERROR_INDEX(LTTNG_ERR_ID_NOT_TRACKED) ] = "ID not tracked", + [ ERROR_INDEX(LTTNG_ERR_PROCESS_ATTR_EXISTS) ] = "Process attribute is already tracked", + [ ERROR_INDEX(LTTNG_ERR_PROCESS_ATTR_MISSING) ] = "Process attribute was not tracked", [ ERROR_INDEX(LTTNG_ERR_INVALID_CHANNEL_DOMAIN) ] = "Invalid channel domain", [ ERROR_INDEX(LTTNG_ERR_OVERFLOW) ] = "Overflow occurred", [ ERROR_INDEX(LTTNG_ERR_SESSION_NOT_STARTED) ] = "Session not started", @@ -217,6 +217,8 @@ static const char *error_string_array[] = { [ ERROR_INDEX(LTTNG_ERR_ROTATION_AFTER_STOP_CLEAR) ] = "Session was already cleared since it became inactive", [ ERROR_INDEX(LTTNG_ERR_USER_NOT_FOUND) ] = "User not found", [ ERROR_INDEX(LTTNG_ERR_GROUP_NOT_FOUND) ] = "Group not found", + [ ERROR_INDEX(LTTNG_ERR_UNSUPPORTED_DOMAIN) ] = "Unsupported domain used", + [ ERROR_INDEX(LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY) ] = "Operation does not apply to the process attribute tracker's tracking policy", /* Last element */ [ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code" diff --git a/src/common/kernel-ctl/kernel-ctl.c b/src/common/kernel-ctl/kernel-ctl.c index 01af4a297..caae421fc 100644 --- a/src/common/kernel-ctl/kernel-ctl.c +++ b/src/common/kernel-ctl/kernel-ctl.c @@ -7,6 +7,7 @@ * */ +#include "lttng/tracker.h" #define _LGPL_SOURCE #define __USE_LINUX_IOCTL_DEFS #include @@ -221,32 +222,32 @@ int kernctl_list_tracker_pids(int fd) } static enum lttng_kernel_tracker_type get_kernel_tracker_type( - enum lttng_tracker_type type) + enum lttng_process_attr process_attr) { - switch (type) { - case LTTNG_TRACKER_PID: + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: return LTTNG_KERNEL_TRACKER_PID; - case LTTNG_TRACKER_VPID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: return LTTNG_KERNEL_TRACKER_VPID; - case LTTNG_TRACKER_UID: + case LTTNG_PROCESS_ATTR_USER_ID: return LTTNG_KERNEL_TRACKER_UID; - case LTTNG_TRACKER_VUID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: return LTTNG_KERNEL_TRACKER_VUID; - case LTTNG_TRACKER_GID: + case LTTNG_PROCESS_ATTR_GROUP_ID: return LTTNG_KERNEL_TRACKER_GID; - case LTTNG_TRACKER_VGID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: return LTTNG_KERNEL_TRACKER_VGID; default: return LTTNG_KERNEL_TRACKER_UNKNOWN; } } -int kernctl_track_id(int fd, enum lttng_tracker_type tracker_type, int id) +int kernctl_track_id(int fd, enum lttng_process_attr process_attr, int id) { struct lttng_kernel_tracker_args args; args.id = id; - args.type = get_kernel_tracker_type(tracker_type); + args.type = get_kernel_tracker_type(process_attr); if (args.type == LTTNG_KERNEL_TRACKER_UNKNOWN) { errno = EINVAL; return -1; @@ -254,12 +255,12 @@ int kernctl_track_id(int fd, enum lttng_tracker_type tracker_type, int id) return LTTNG_IOCTL_CHECK(fd, LTTNG_KERNEL_SESSION_TRACK_ID, &args); } -int kernctl_untrack_id(int fd, enum lttng_tracker_type tracker_type, int id) +int kernctl_untrack_id(int fd, enum lttng_process_attr process_attr, int id) { struct lttng_kernel_tracker_args args; args.id = id; - args.type = get_kernel_tracker_type(tracker_type); + args.type = get_kernel_tracker_type(process_attr); if (args.type == LTTNG_KERNEL_TRACKER_UNKNOWN) { errno = EINVAL; return -1; @@ -267,12 +268,12 @@ int kernctl_untrack_id(int fd, enum lttng_tracker_type tracker_type, int id) return LTTNG_IOCTL_CHECK(fd, LTTNG_KERNEL_SESSION_UNTRACK_ID, &args); } -int kernctl_list_tracker_ids(int fd, enum lttng_tracker_type tracker_type) +int kernctl_list_tracker_ids(int fd, enum lttng_process_attr process_attr) { struct lttng_kernel_tracker_args args; args.id = -1; - args.type = get_kernel_tracker_type(tracker_type); + args.type = get_kernel_tracker_type(process_attr); if (args.type == LTTNG_KERNEL_TRACKER_UNKNOWN) { errno = EINVAL; return -1; diff --git a/src/common/kernel-ctl/kernel-ctl.h b/src/common/kernel-ctl/kernel-ctl.h index f8eac8d56..60fcabd6e 100644 --- a/src/common/kernel-ctl/kernel-ctl.h +++ b/src/common/kernel-ctl/kernel-ctl.h @@ -55,9 +55,9 @@ int kernctl_track_pid(int fd, int pid); int kernctl_untrack_pid(int fd, int pid); int kernctl_list_tracker_pids(int fd); -int kernctl_track_id(int fd, enum lttng_tracker_type tracker_type, int id); -int kernctl_untrack_id(int fd, enum lttng_tracker_type tracker_type, int id); -int kernctl_list_tracker_ids(int fd, enum lttng_tracker_type tracker_type); +int kernctl_track_id(int fd, enum lttng_process_attr process_attr, int id); +int kernctl_untrack_id(int fd, enum lttng_process_attr process_attr, int id); +int kernctl_list_tracker_ids(int fd, enum lttng_process_attr process_attr); int kernctl_session_regenerate_metadata(int fd); int kernctl_session_regenerate_statedump(int fd); diff --git a/src/common/macros.h b/src/common/macros.h index e52d7f771..cce09a6cb 100644 --- a/src/common/macros.h +++ b/src/common/macros.h @@ -77,6 +77,8 @@ void *zmalloc(size_t len) #define LTTNG_PACKED __attribute__((__packed__)) #endif +#define is_signed(type) (((type) (-1)) < 0) + /* * Align value to the next multiple of align. Returns val if it already is a * multiple of align. Align must be a power of two. diff --git a/src/common/mi-lttng-4.0.xsd b/src/common/mi-lttng-4.0.xsd index daa8b5e5a..fef655096 100644 --- a/src/common/mi-lttng-4.0.xsd +++ b/src/common/mi-lttng-4.0.xsd @@ -317,14 +317,6 @@ SPDX-License-Identifier: MIT - - - - - - - - @@ -332,33 +324,31 @@ SPDX-License-Identifier: MIT - + - - + - + - - + + - + - + - - + @@ -369,33 +359,31 @@ SPDX-License-Identifier: MIT - + - - + - + - - + + - + - + - - + @@ -406,7 +394,7 @@ SPDX-License-Identifier: MIT - + @@ -414,25 +402,24 @@ SPDX-License-Identifier: MIT - + - + - - + + - + - - + + - - + @@ -443,7 +430,7 @@ SPDX-License-Identifier: MIT - + @@ -451,25 +438,24 @@ SPDX-License-Identifier: MIT - + - + - - + + - + - - + + - - + @@ -480,7 +466,7 @@ SPDX-License-Identifier: MIT - + @@ -488,25 +474,24 @@ SPDX-License-Identifier: MIT - + - + - - + + - + - - + + - - + @@ -517,7 +502,7 @@ SPDX-License-Identifier: MIT - + @@ -525,38 +510,37 @@ SPDX-License-Identifier: MIT - + - + - - + + - + - - + + - - + - - + + - - - - - - + + + + + + @@ -569,7 +553,7 @@ SPDX-License-Identifier: MIT - + @@ -870,7 +854,7 @@ SPDX-License-Identifier: MIT - + diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index 5160e0a58..71253fcd2 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -7,13 +7,14 @@ * */ +#include "lttng/tracker.h" #define _LGPL_SOURCE +#include "mi-lttng.h" #include #include -#include -#include +#include #include -#include "mi-lttng.h" +#include #include @@ -1528,39 +1529,52 @@ end: LTTNG_HIDDEN int mi_lttng_trackers_open(struct mi_writer *writer) { - return mi_lttng_writer_open_element(writer, config_element_trackers); + return mi_lttng_writer_open_element( + writer, config_element_process_attr_trackers); } -static int get_tracker_elements(enum lttng_tracker_type tracker_type, - const char **element_id_tracker, - const char **element_target_id) +static int get_tracker_elements(enum lttng_process_attr process_attr, + const char **element_process_attr_tracker, + const char **element_process_attr_value) { int ret = 0; - switch (tracker_type) { - case LTTNG_TRACKER_PID: - *element_id_tracker = config_element_pid_tracker; - *element_target_id = config_element_target_pid; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + *element_process_attr_tracker = + config_element_process_attr_tracker_pid; + *element_process_attr_value = + config_element_process_attr_pid_value; break; - case LTTNG_TRACKER_VPID: - *element_id_tracker = config_element_vpid_tracker; - *element_target_id = config_element_target_vpid; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + *element_process_attr_tracker = + config_element_process_attr_tracker_vpid; + *element_process_attr_value = + config_element_process_attr_vpid_value; break; - case LTTNG_TRACKER_UID: - *element_id_tracker = config_element_uid_tracker; - *element_target_id = config_element_target_uid; + case LTTNG_PROCESS_ATTR_USER_ID: + *element_process_attr_tracker = + config_element_process_attr_tracker_uid; + *element_process_attr_value = + config_element_process_attr_uid_value; break; - case LTTNG_TRACKER_VUID: - *element_id_tracker = config_element_vuid_tracker; - *element_target_id = config_element_target_vuid; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + *element_process_attr_tracker = + config_element_process_attr_tracker_vuid; + *element_process_attr_value = + config_element_process_attr_vuid_value; break; - case LTTNG_TRACKER_GID: - *element_id_tracker = config_element_gid_tracker; - *element_target_id = config_element_target_gid; + case LTTNG_PROCESS_ATTR_GROUP_ID: + *element_process_attr_tracker = + config_element_process_attr_tracker_gid; + *element_process_attr_value = + config_element_process_attr_gid_value; break; - case LTTNG_TRACKER_VGID: - *element_id_tracker = config_element_vgid_tracker; - *element_target_id = config_element_target_vgid; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + *element_process_attr_tracker = + config_element_process_attr_tracker_vgid; + *element_process_attr_value = + config_element_process_attr_vgid_value; break; default: ret = LTTNG_ERR_SAVE_IO_FAIL; @@ -1569,26 +1583,26 @@ static int get_tracker_elements(enum lttng_tracker_type tracker_type, } LTTNG_HIDDEN -int mi_lttng_id_tracker_open( - struct mi_writer *writer, enum lttng_tracker_type tracker_type) +int mi_lttng_process_attribute_tracker_open( + struct mi_writer *writer, enum lttng_process_attr process_attr) { int ret; - const char *element_id_tracker, *element_target_id; + const char *element_tracker, *element_value; ret = get_tracker_elements( - tracker_type, &element_id_tracker, &element_target_id); + process_attr, &element_tracker, &element_value); if (ret) { return ret; } - /* Open element $id_tracker */ - ret = mi_lttng_writer_open_element(writer, element_id_tracker); + /* Open process attribute tracker element */ + ret = mi_lttng_writer_open_element(writer, element_tracker); if (ret) { goto end; } - /* Open targets element */ - ret = mi_lttng_targets_open(writer); + /* Open values element */ + ret = mi_lttng_process_attr_values_open(writer); end: return ret; } @@ -1643,104 +1657,137 @@ end: } LTTNG_HIDDEN -int mi_lttng_targets_open(struct mi_writer *writer) +int mi_lttng_process_attr_values_open(struct mi_writer *writer) { - return mi_lttng_writer_open_element(writer, - config_element_targets); + return mi_lttng_writer_open_element( + writer, config_element_process_attr_values); } LTTNG_HIDDEN -int mi_lttng_id_target(struct mi_writer *writer, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id, - int is_open) +int mi_lttng_all_process_attribute_value(struct mi_writer *writer, + enum lttng_process_attr process_attr, + bool is_open) { int ret; const char *element_id_tracker, *element_target_id; - enum lttng_tracker_id_status status; - int value; - const char *string; ret = get_tracker_elements( - tracker_type, &element_id_tracker, &element_target_id); + process_attr, &element_id_tracker, &element_target_id); if (ret) { return ret; } - switch (lttng_tracker_id_get_type(id)) { - case LTTNG_ID_ALL: - ret = mi_lttng_writer_open_element(writer, element_target_id); - if (ret) { - goto end; - } - ret = mi_lttng_writer_open_element(writer, config_element_type); - if (ret) { - goto end; - } - ret = mi_lttng_writer_write_element_bool( - writer, config_element_all, 1); - if (ret) { - goto end; - } - ret = mi_lttng_writer_close_element(writer); - if (ret) { - goto end; - } - break; - case LTTNG_ID_VALUE: - ret = mi_lttng_writer_open_element(writer, element_target_id); - if (ret) { - goto end; - } - ret = mi_lttng_writer_open_element(writer, config_element_type); - if (ret) { - goto end; - } + ret = mi_lttng_writer_open_element(writer, element_target_id); + if (ret) { + goto end; + } - status = lttng_tracker_id_get_value(id, &value); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -1; - goto end; - } + ret = mi_lttng_writer_open_element(writer, config_element_type); + if (ret) { + goto end; + } - ret = mi_lttng_writer_write_element_signed_int( - writer, config_element_id, value); - if (ret) { - goto end; - } + ret = mi_lttng_writer_write_element_bool(writer, config_element_all, 1); + if (ret) { + goto end; + } + + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto end; + } + + if (!is_open) { ret = mi_lttng_writer_close_element(writer); if (ret) { goto end; } - break; - case LTTNG_ID_STRING: - ret = mi_lttng_writer_open_element(writer, element_target_id); - if (ret) { - goto end; - } - ret = mi_lttng_writer_open_element(writer, config_element_type); - if (ret) { - goto end; - } + } +end: + return ret; +} - status = lttng_tracker_id_get_string(id, &string); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -1; - goto end; - } +LTTNG_HIDDEN +int mi_lttng_integral_process_attribute_value(struct mi_writer *writer, + enum lttng_process_attr process_attr, + int64_t value, + bool is_open) +{ + int ret; + const char *element_id_tracker, *element_target_id; - ret = mi_lttng_writer_write_element_string( - writer, config_element_name, string); - if (ret) { - goto end; - } + ret = get_tracker_elements( + process_attr, &element_id_tracker, &element_target_id); + if (ret) { + return ret; + } + + ret = mi_lttng_writer_open_element(writer, element_target_id); + if (ret) { + goto end; + } + + ret = mi_lttng_writer_open_element(writer, config_element_type); + if (ret) { + goto end; + } + + ret = mi_lttng_writer_write_element_signed_int( + writer, config_element_process_attr_id, value); + if (ret) { + goto end; + } + + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto end; + } + + if (!is_open) { ret = mi_lttng_writer_close_element(writer); if (ret) { goto end; } - break; - case LTTNG_ID_UNKNOWN: - ret = -LTTNG_ERR_INVALID; + } + +end: + return ret; +} + +LTTNG_HIDDEN +int mi_lttng_string_process_attribute_value(struct mi_writer *writer, + enum lttng_process_attr process_attr, + const char *value, + bool is_open) + +{ + int ret; + const char *element_id_tracker, *element_target_id; + + ret = get_tracker_elements( + process_attr, &element_id_tracker, &element_target_id); + if (ret) { + return ret; + } + + ret = mi_lttng_writer_open_element(writer, element_target_id); + if (ret) { + goto end; + } + + ret = mi_lttng_writer_open_element(writer, config_element_type); + if (ret) { + goto end; + } + + ret = mi_lttng_writer_write_element_string( + writer, config_element_name, value); + if (ret) { + goto end; + } + + ret = mi_lttng_writer_close_element(writer); + if (ret) { goto end; } diff --git a/src/common/mi-lttng.h b/src/common/mi-lttng.h index a5c448023..9c985f6bb 100644 --- a/src/common/mi-lttng.h +++ b/src/common/mi-lttng.h @@ -596,7 +596,7 @@ int mi_lttng_event_fields_open(struct mi_writer *writer); int mi_lttng_trackers_open(struct mi_writer *writer); /* - * Machine interface: open a id tracker element. + * Machine interface: open a process attribute tracker element. * * writer An instance of a machine interface writer. * @@ -605,8 +605,8 @@ int mi_lttng_trackers_open(struct mi_writer *writer); * * Note: A targets element is also opened for each tracker definition */ -int mi_lttng_id_tracker_open( - struct mi_writer *writer, enum lttng_tracker_type tracker_type); +int mi_lttng_process_attribute_tracker_open( + struct mi_writer *writer, enum lttng_process_attr process_attr); /* * Machine interface: open a PIDs element. @@ -664,28 +664,54 @@ int mi_lttng_process(struct mi_writer *writer, pid_t pid , const char *name, */ int mi_lttng_pid(struct mi_writer *writer, pid_t pid , const char *name, int is_open); + /* - * Machine interface: open a targets element. + * Machine interface: open a process attribute values element. * * writer An instance of a machine interface writer. * * Returns zero if the element's value could be written. * Negative values indicate an error. */ -int mi_lttng_targets_open(struct mi_writer *writer); +int mi_lttng_process_attr_values_open(struct mi_writer *writer); /* - * Machine interface for track/untrack an id_target + * Machine interface for track/untrack of all process attribute values. * * writer An instance of a machine interface writer. * * Returns zero if the element's value could be written. * Negative values indicate an error. */ -int mi_lttng_id_target(struct mi_writer *writer, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id, - int is_open); +int mi_lttng_all_process_attribute_value(struct mi_writer *writer, + enum lttng_process_attr process_attr, + bool is_open); + +/* + * Machine interface for track/untrack of an integral process attribute value. + * + * writer An instance of a machine interface writer. + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_integral_process_attribute_value(struct mi_writer *writer, + enum lttng_process_attr process_attr, + int64_t value, + bool is_open); + +/* + * Machine interface for track/untrack of a string process attribute value. + * + * writer An instance of a machine interface writer. + * + * Returns zero if the element's value could be written. + * Negative values indicate an error. + */ +int mi_lttng_string_process_attribute_value(struct mi_writer *writer, + enum lttng_process_attr process_attr, + const char *value, + bool is_open); /* * Machine interface of a context. diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index d89da4e32..fd1ceae11 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -50,55 +50,57 @@ enum lttcomm_sessiond_command { /* Tracer command */ - LTTNG_ADD_CONTEXT = 0, + LTTNG_ADD_CONTEXT = 0, /* LTTNG_CALIBRATE used to be here */ - LTTNG_DISABLE_CHANNEL = 2, - LTTNG_DISABLE_EVENT = 3, - LTTNG_LIST_SYSCALLS = 4, - LTTNG_ENABLE_CHANNEL = 5, - LTTNG_ENABLE_EVENT = 6, + LTTNG_DISABLE_CHANNEL = 2, + LTTNG_DISABLE_EVENT = 3, + LTTNG_LIST_SYSCALLS = 4, + LTTNG_ENABLE_CHANNEL = 5, + LTTNG_ENABLE_EVENT = 6, /* 7 */ /* Session daemon command */ /* 8 */ - LTTNG_DESTROY_SESSION = 9, - LTTNG_LIST_CHANNELS = 10, - LTTNG_LIST_DOMAINS = 11, - LTTNG_LIST_EVENTS = 12, - LTTNG_LIST_SESSIONS = 13, - LTTNG_LIST_TRACEPOINTS = 14, - LTTNG_REGISTER_CONSUMER = 15, - LTTNG_START_TRACE = 16, - LTTNG_STOP_TRACE = 17, - LTTNG_LIST_TRACEPOINT_FIELDS = 18, + LTTNG_DESTROY_SESSION = 9, + LTTNG_LIST_CHANNELS = 10, + LTTNG_LIST_DOMAINS = 11, + LTTNG_LIST_EVENTS = 12, + LTTNG_LIST_SESSIONS = 13, + LTTNG_LIST_TRACEPOINTS = 14, + LTTNG_REGISTER_CONSUMER = 15, + LTTNG_START_TRACE = 16, + LTTNG_STOP_TRACE = 17, + LTTNG_LIST_TRACEPOINT_FIELDS = 18, /* Consumer */ - LTTNG_DISABLE_CONSUMER = 19, - LTTNG_ENABLE_CONSUMER = 20, - LTTNG_SET_CONSUMER_URI = 21, + LTTNG_DISABLE_CONSUMER = 19, + LTTNG_ENABLE_CONSUMER = 20, + LTTNG_SET_CONSUMER_URI = 21, /* 22 */ /* 23 */ - LTTNG_DATA_PENDING = 24, - LTTNG_SNAPSHOT_ADD_OUTPUT = 25, - LTTNG_SNAPSHOT_DEL_OUTPUT = 26, - LTTNG_SNAPSHOT_LIST_OUTPUT = 27, - LTTNG_SNAPSHOT_RECORD = 28, + LTTNG_DATA_PENDING = 24, + LTTNG_SNAPSHOT_ADD_OUTPUT = 25, + LTTNG_SNAPSHOT_DEL_OUTPUT = 26, + LTTNG_SNAPSHOT_LIST_OUTPUT = 27, + LTTNG_SNAPSHOT_RECORD = 28, /* 29 */ /* 30 */ - LTTNG_SAVE_SESSION = 31, - LTTNG_TRACK_ID = 32, - LTTNG_UNTRACK_ID = 33, - LTTNG_LIST_TRACKER_IDS = 34, - LTTNG_SET_SESSION_SHM_PATH = 40, - LTTNG_REGENERATE_METADATA = 41, - LTTNG_REGENERATE_STATEDUMP = 42, - LTTNG_REGISTER_TRIGGER = 43, - LTTNG_UNREGISTER_TRIGGER = 44, - LTTNG_ROTATE_SESSION = 45, - LTTNG_ROTATION_GET_INFO = 46, - LTTNG_ROTATION_SET_SCHEDULE = 47, - LTTNG_SESSION_LIST_ROTATION_SCHEDULES = 48, - LTTNG_CREATE_SESSION_EXT = 49, - LTTNG_CLEAR_SESSION = 50, + LTTNG_SAVE_SESSION = 31, + LTTNG_PROCESS_ATTR_TRACKER_ADD_INCLUDE_VALUE = 32, + LTTNG_PROCESS_ATTR_TRACKER_REMOVE_INCLUDE_VALUE = 33, + LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY = 34, + LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY = 35, + LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET = 36, + LTTNG_SET_SESSION_SHM_PATH = 40, + LTTNG_REGENERATE_METADATA = 41, + LTTNG_REGENERATE_STATEDUMP = 42, + LTTNG_REGISTER_TRIGGER = 43, + LTTNG_UNREGISTER_TRIGGER = 44, + LTTNG_ROTATE_SESSION = 45, + LTTNG_ROTATION_GET_INFO = 46, + LTTNG_ROTATION_SET_SCHEDULE = 47, + LTTNG_SESSION_LIST_ROTATION_SCHEDULES = 48, + LTTNG_CREATE_SESSION_EXT = 49, + LTTNG_CLEAR_SESSION = 50, }; enum lttcomm_relayd_command { @@ -257,6 +259,13 @@ struct lttcomm_proto_ops { size_t len, int flags); }; +struct process_attr_integral_value_comm { + union { + int64_t _signed; + uint64_t _unsigned; + } u; +} LTTNG_PACKED; + /* * Data structure received from lttng client to session daemon. */ @@ -344,21 +353,35 @@ struct lttcomm_session_msg { char shm_path[PATH_MAX]; } LTTNG_PACKED set_shm_path; struct { - uint32_t tracker_type; /* enum lttng_tracker_type */ - uint32_t id_type; /* enum lttng_tracker_id_type */ - union { - int32_t value; - uint32_t var_len; - } u; + /* enum lttng_process_attr */ + int32_t process_attr; + /* enum lttng_process_attr_value_type */ + int32_t value_type; + + struct process_attr_integral_value_comm integral_value; /* - * for LTTNG_ID_STRING, followed by a variable length - * zero-terminated string of length "var_len", which - * includes the final \0. + * For user/group names, a variable length, + * zero-terminated, string of length 'name_len' + * (including the terminator) follows. + * + * integral_value should not be used in those cases. */ - } LTTNG_PACKED id_tracker; + uint32_t name_len; + } LTTNG_PACKED process_attr_tracker_add_remove_include_value; struct { - uint32_t tracker_type; /* enum lttng_tracker_type */ - } LTTNG_PACKED id_tracker_list; + /* enum lttng_process_attr */ + int32_t process_attr; + } LTTNG_PACKED process_attr_tracker_get_inclusion_set; + struct { + /* enum lttng_process_attr */ + int32_t process_attr; + } LTTNG_PACKED process_attr_tracker_get_tracking_policy; + struct { + /* enum lttng_process_attr */ + int32_t process_attr; + /* enum lttng_tracking_policy */ + int32_t tracking_policy; + } LTTNG_PACKED process_attr_tracker_set_tracking_policy; struct { uint32_t length; } LTTNG_PACKED trigger; @@ -469,14 +492,6 @@ struct lttcomm_tracker_command_header { uint32_t nb_tracker_id; } LTTNG_PACKED; -struct lttcomm_tracker_id_header { - uint32_t type; /* enum lttng_tracker_id_type */ - union { - int32_t value; - uint32_t var_data_len; - } u; -} LTTNG_PACKED; - /* * Data structure for the response from sessiond to the lttng client. */ diff --git a/src/common/tracker.c b/src/common/tracker.c index c07ea536b..532a924b5 100644 --- a/src/common/tracker.c +++ b/src/common/tracker.c @@ -1,370 +1,519 @@ /* * Copyright (C) 2019 Jonathan Rajotte + * Copyright (C) 2020 Jérémie Galarneau * * SPDX-License-Identifier: LGPL-2.1-only * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct lttng_tracker_id *lttng_tracker_id_create(void) -{ - struct lttng_tracker_id *id; +#include +#include +#include - id = zmalloc(sizeof(*id)); - if (!id) { - goto error; +#include +#include +#include +#include +#include + +#include + +struct process_attr_tracker_values_comm_header { + uint32_t count; +}; + +struct process_attr_tracker_value_comm { + /* enum lttng_process_attr_value_type */ + int32_t type; + union { + struct process_attr_integral_value_comm integral; + /* Includes the '\0' terminator. */ + uint32_t name_len; + } value; +}; + +#define GET_INTEGRAL_COMM_VALUE(value_ptr, as_type) \ + ((as_type)(is_signed(as_type) ? (value_ptr)->u._signed : \ + (value_ptr)->u._unsigned)) + +#define SET_INTEGRAL_COMM_VALUE(comm_value, value) \ + if (is_signed(typeof(value))) { \ + (comm_value)->u._signed = \ + (typeof((comm_value)->u._signed)) value; \ + } else { \ + (comm_value)->u._unsigned = \ + (typeof((comm_value)->u._unsigned)) value; \ } - id->type = LTTNG_ID_UNKNOWN; - id->string = NULL; - id->value = -1; - return id; -error: - lttng_tracker_id_destroy(id); - return NULL; +static inline bool is_virtual_process_attr(enum lttng_process_attr process_attr) +{ + return process_attr == LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID || + process_attr == LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID || + process_attr == LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID; } -enum lttng_tracker_id_status lttng_tracker_id_set_value( - struct lttng_tracker_id *id, int value) +static inline bool is_value_type_name( + enum lttng_process_attr_value_type value_type) { - assert(id); - - if (value < 0) { - return LTTNG_TRACKER_ID_STATUS_INVALID; - } - - id->type = LTTNG_ID_VALUE; - id->value = value; - return LTTNG_TRACKER_ID_STATUS_OK; + return value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME || + value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME; } -enum lttng_tracker_id_status lttng_tracker_id_set_string( - struct lttng_tracker_id *id, const char *value) +LTTNG_HIDDEN +enum lttng_error_code process_attr_value_from_comm( + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + enum lttng_process_attr_value_type value_type, + const struct process_attr_integral_value_comm *integral_value, + const struct lttng_buffer_view *value_view, + struct process_attr_value **_value) { - assert(id); - assert(value); + char *name = NULL; + enum lttng_error_code ret = LTTNG_OK; + struct process_attr_value *value = zmalloc(sizeof(*value)); - id->type = LTTNG_ID_STRING; - id->string = strdup(value); - if (id->string == NULL) { - /* No memory left */ + if (!value) { + ret = LTTNG_ERR_NOMEM; goto error; } - return LTTNG_TRACKER_ID_STATUS_OK; -error: - return LTTNG_TRACKER_ID_STATUS_INVALID; -} - -enum lttng_tracker_id_status lttng_tracker_id_set_all( - struct lttng_tracker_id *id) -{ - assert(id); + if (value_view && value_view->size > 0) { + if (value_view->data[value_view->size - 1] != '\0') { + ret = LTTNG_ERR_INVALID; + goto error; + } + name = strdup(value_view->data); + if (!name) { + ret = LTTNG_ERR_NOMEM; + } + } - id->type = LTTNG_ID_ALL; + if (domain != LTTNG_DOMAIN_UST && domain != LTTNG_DOMAIN_KERNEL) { + ERR("Only the user space and kernel space domains may be specified to configure process attribute trackers"); + ret = LTTNG_ERR_UNSUPPORTED_DOMAIN; + goto error; + } - return LTTNG_TRACKER_ID_STATUS_OK; -} + if (!is_virtual_process_attr(process_attr) && + domain != LTTNG_DOMAIN_KERNEL) { + ERR("Non-virtual process attributes can only be used in the kernel domain"); + ret = LTTNG_ERR_UNSUPPORTED_DOMAIN; + goto error; + } -static void lttng_tracker_id_reset(struct lttng_tracker_id *id) -{ - if (id == NULL) { - return; + /* Only expect a payload for name value types. */ + if (is_value_type_name(value_type) && value_view->size == 0) { + ret = LTTNG_ERR_INVALID_PROTOCOL; + goto error; + } else if (!is_value_type_name(value_type) && value_view->size != 0) { + ret = LTTNG_ERR_INVALID_PROTOCOL; + goto error; } - if (id->string != NULL) { - free(id->string); - id->string = NULL; + value->type = value_type; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + if (value_type != LTTNG_PROCESS_ATTR_VALUE_TYPE_PID) { + ERR("Invalid value type used for process ID process attribute"); + ret = LTTNG_ERR_INVALID; + goto error; + } + value->value.pid = + GET_INTEGRAL_COMM_VALUE(integral_value, pid_t); + break; + case LTTNG_PROCESS_ATTR_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + switch (value_type) { + case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID: + value->value.uid = GET_INTEGRAL_COMM_VALUE( + integral_value, uid_t); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME: + if (!name) { + ret = LTTNG_ERR_INVALID; + goto error; + } + + value->value.user_name = name; + name = NULL; + break; + default: + ERR("Invalid value type used for user ID process attribute"); + ret = LTTNG_ERR_INVALID; + goto error; + } + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + switch (value_type) { + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID: + value->value.gid = GET_INTEGRAL_COMM_VALUE( + integral_value, gid_t); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME: + if (!name) { + ret = LTTNG_ERR_INVALID; + goto error; + } + + value->value.group_name = name; + name = NULL; + break; + default: + ERR("Invalid value type used for group ID process attribute"); + ret = LTTNG_ERR_INVALID; + goto error; + } + break; + default: + ret = LTTNG_ERR_INVALID_PROTOCOL; + goto error; } - id->type = LTTNG_ID_UNKNOWN; - id->value = -1; + *_value = value; + value = NULL; + return LTTNG_OK; +error: + free(name); + process_attr_value_destroy(value); + return ret; } -void lttng_tracker_id_destroy(struct lttng_tracker_id *id) +LTTNG_HIDDEN +const char *lttng_process_attr_to_string(enum lttng_process_attr process_attr) { - if (id == NULL) { - return; + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + return "process ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + return "virtual process ID"; + case LTTNG_PROCESS_ATTR_USER_ID: + return "user ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + return "virtual user ID"; + case LTTNG_PROCESS_ATTR_GROUP_ID: + return "group ID"; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + return "virtual group ID"; + default: + return "unknown process attribute"; } - - lttng_tracker_id_reset(id); - - free(id); } -enum lttng_tracker_id_type lttng_tracker_id_get_type( - const struct lttng_tracker_id *id) +static void process_attr_tracker_value_destructor(void *ptr) { - assert(id); - return id->type; + struct process_attr_value *value = (typeof(value)) ptr; + + process_attr_value_destroy(value); } -enum lttng_tracker_id_status lttng_tracker_id_get_value( - const struct lttng_tracker_id *id, int *value) +LTTNG_HIDDEN +struct lttng_process_attr_values *lttng_process_attr_values_create(void) { - assert(id); - if (id->type == LTTNG_ID_UNKNOWN) { - return LTTNG_TRACKER_ID_STATUS_UNSET; - } + struct lttng_process_attr_values *values = zmalloc(sizeof(*values)); - if (id->type != LTTNG_ID_VALUE) { - return LTTNG_TRACKER_ID_STATUS_INVALID; + if (!values) { + goto end; } - *value = id->value; - return LTTNG_TRACKER_ID_STATUS_OK; + lttng_dynamic_pointer_array_init( + &values->array, process_attr_tracker_value_destructor); +end: + return values; } -bool lttng_tracker_id_is_equal(const struct lttng_tracker_id *left, - const struct lttng_tracker_id *right) +LTTNG_HIDDEN +unsigned int _lttng_process_attr_values_get_count( + const struct lttng_process_attr_values *values) { - if (left->type != right->type) { - return 0; - } - - switch (left->type) { - case LTTNG_ID_ALL: - return 1; - case LTTNG_ID_VALUE: - if (left->value != right->value) { - return 0; - } - break; - case LTTNG_ID_STRING: - if (strcmp(left->string, right->string) != 0) { - return 0; - } - break; - default: - /* - * Normally this should return true, but comparing unset tracker - * id is "invalid". - */ - return 0; - } - return 1; + return (unsigned int) lttng_dynamic_pointer_array_get_count( + &values->array); } -int lttng_tracker_id_copy(struct lttng_tracker_id *dest, - const struct lttng_tracker_id *orig) +LTTNG_HIDDEN +const struct process_attr_value *lttng_process_attr_tracker_values_get_at_index( + const struct lttng_process_attr_values *values, + unsigned int index) { - int ret = 0; - enum lttng_tracker_id_status status; - - assert(dest); - assert(orig); + return lttng_dynamic_pointer_array_get_pointer(&values->array, index); +} - switch (orig->type) { - case LTTNG_ID_ALL: - status = lttng_tracker_id_set_all(dest); +static +int process_attr_tracker_value_serialize(const struct process_attr_value *value, + struct lttng_dynamic_buffer *buffer) +{ + int ret; + struct process_attr_tracker_value_comm value_comm = { + .type = (int32_t) value->type, + }; + const char *name = NULL; + + switch (value->type) { + case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID: + SET_INTEGRAL_COMM_VALUE( + &value_comm.value.integral, value->value.pid); break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_set_value(dest, orig->value); + case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID: + SET_INTEGRAL_COMM_VALUE( + &value_comm.value.integral, value->value.uid); break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_set_string(dest, orig->string); + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID: + SET_INTEGRAL_COMM_VALUE( + &value_comm.value.integral, value->value.gid); break; - default: - status = LTTNG_TRACKER_ID_STATUS_OK; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME: + name = value->value.user_name; break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME: + name = value->value.group_name; + break; + default: + abort(); } - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -1; - goto error; + if (name) { + value_comm.value.name_len = strlen(name) + 1; } -error: + + ret = lttng_dynamic_buffer_append( + buffer, &value_comm, sizeof(value_comm)); + if (ret) { + goto end; + } + + if (name) { + ret = lttng_dynamic_buffer_append( + buffer, name, value_comm.value.name_len); + } +end: return ret; } -struct lttng_tracker_id *lttng_tracker_id_duplicate( - const struct lttng_tracker_id *orig) +LTTNG_HIDDEN +int lttng_process_attr_values_serialize( + const struct lttng_process_attr_values *values, + struct lttng_dynamic_buffer *buffer) { int ret; - struct lttng_tracker_id *copy = NULL; + unsigned int count, i; + struct process_attr_tracker_values_comm_header header = {}; - copy = lttng_tracker_id_create(); - if (copy == NULL) { - goto error; - } + count = _lttng_process_attr_values_get_count(values); + header.count = (uint32_t) count; - ret = lttng_tracker_id_copy(copy, orig); + ret = lttng_dynamic_buffer_append(buffer, &header, sizeof(header)); if (ret) { - goto error; + goto end; } - return copy; -error: - lttng_tracker_id_destroy(copy); - return NULL; -} - -enum lttng_tracker_id_status lttng_tracker_id_get_string( - const struct lttng_tracker_id *id, const char **value) -{ - assert(id); - if (id->type == LTTNG_ID_UNKNOWN) { - *value = NULL; - return LTTNG_TRACKER_ID_STATUS_UNSET; - } + for (i = 0; i < count; i++) { + const struct process_attr_value *value = + lttng_process_attr_tracker_values_get_at_index( + values, i); - if (id->type != LTTNG_ID_STRING) { - *value = NULL; - return LTTNG_TRACKER_ID_STATUS_INVALID; + ret = process_attr_tracker_value_serialize(value, buffer); + if (ret) { + goto end; + } } - - *value = id->string; - return LTTNG_TRACKER_ID_STATUS_OK; +end: + return ret; } -struct lttng_tracker_ids *lttng_tracker_ids_create(unsigned int count) +LTTNG_HIDDEN +ssize_t lttng_process_attr_values_create_from_buffer( + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + const struct lttng_buffer_view *buffer_view, + struct lttng_process_attr_values **_values) { - struct lttng_tracker_ids *ids = NULL; + ssize_t offset; + unsigned int i; + struct lttng_process_attr_values *values; + struct lttng_buffer_view header_view; + const struct process_attr_tracker_values_comm_header *header; - ids = zmalloc(sizeof(*ids)); - if (!ids) { + values = lttng_process_attr_values_create(); + if (!values) { goto error; } - ids->id_array = zmalloc(sizeof(struct lttng_tracker_id) * count); - if (!ids->id_array) { + header_view = lttng_buffer_view_from_view( + buffer_view, 0, sizeof(*header)); + if (!header_view.data) { goto error; } + offset = header_view.size; + header = (typeof(header)) header_view.data; + + /* + * Check that the number of values is not absurdly large with respect to + * the received buffer's size. + */ + if (buffer_view->size < + header->count * sizeof(struct process_attr_tracker_value_comm)) { + goto error; + } + for (i = 0; i < (unsigned int) header->count; i++) { + int ret; + enum lttng_error_code ret_code; + const struct process_attr_tracker_value_comm *value_comm; + struct process_attr_value *value; + enum lttng_process_attr_value_type type; + struct lttng_buffer_view value_view; + struct lttng_buffer_view value_name_view = {}; + + value_view = lttng_buffer_view_from_view( + buffer_view, offset, sizeof(*value_comm)); + if (!value_view.data) { + goto error; + } - ids->count = count; + offset += value_view.size; + value_comm = (typeof(value_comm)) value_view.data; + type = (typeof(type)) value_comm->type; - return ids; -error: - free(ids); - return NULL; -} + if (is_value_type_name(type)) { + value_name_view = lttng_buffer_view_from_view( + buffer_view, offset, + value_comm->value.name_len); + offset += value_name_view.size; + } + ret_code = process_attr_value_from_comm(domain, process_attr, + type, &value_comm->value.integral, + &value_name_view, &value); + if (ret_code != LTTNG_OK) { + goto error; + } -LTTNG_HIDDEN -struct lttng_tracker_id *lttng_tracker_ids_get_pointer_of_index( - const struct lttng_tracker_ids *ids, unsigned int index) -{ - assert(ids); - if (index >= ids->count) { - return NULL; + ret = lttng_dynamic_pointer_array_add_pointer( + &values->array, value); + if (ret) { + process_attr_value_destroy(value); + goto error; + } } - return &ids->id_array[index]; + *_values = values; + return offset; +error: + lttng_process_attr_values_destroy(values); + return -1; } -const struct lttng_tracker_id *lttng_tracker_ids_get_at_index( - const struct lttng_tracker_ids *ids, unsigned int index) +LTTNG_HIDDEN +void lttng_process_attr_values_destroy(struct lttng_process_attr_values *values) { - assert(ids); - return lttng_tracker_ids_get_pointer_of_index(ids, index); + if (!values) { + return; + } + lttng_dynamic_pointer_array_reset(&values->array); + free(values); } -enum lttng_tracker_id_status lttng_tracker_ids_get_count(const struct lttng_tracker_ids *ids, unsigned int *count) +LTTNG_HIDDEN +struct process_attr_value *process_attr_value_copy( + const struct process_attr_value *value) { + struct process_attr_value *new_value = NULL; - enum lttng_tracker_id_status status = LTTNG_TRACKER_ID_STATUS_OK; - - if (!ids || !count) { - status = LTTNG_TRACKER_ID_STATUS_INVALID; + if (!value) { goto end; } - *count = ids->count; + new_value = zmalloc(sizeof(*new_value)); + if (!new_value) { + goto end; + } + if (is_value_type_name(value->type)) { + const char *src = + value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME ? + value->value.user_name : + value->value.group_name; + char **dst = value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME ? + &new_value->value.user_name : + &new_value->value.group_name; + + new_value->type = value->type; + *dst = strdup(src); + if (!*dst) { + goto error; + } + } else { + *new_value = *value; + } end: - return status; + return new_value; +error: + free(new_value); + return NULL; } -void lttng_tracker_ids_destroy(struct lttng_tracker_ids *ids) +LTTNG_HIDDEN +unsigned long process_attr_value_hash(const struct process_attr_value *a) { - int i; + unsigned long hash = hash_key_ulong((void *) a->type, lttng_ht_seed); - if (!ids) { - return; + switch (a->type) { + case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID: + hash ^= hash_key_ulong((void *) (unsigned long) a->value.pid, + lttng_ht_seed); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID: + hash ^= hash_key_ulong((void *) (unsigned long) a->value.uid, + lttng_ht_seed); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID: + hash ^= hash_key_ulong((void *) (unsigned long) a->value.gid, + lttng_ht_seed); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME: + hash ^= hash_key_str(a->value.user_name, lttng_ht_seed); + break; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME: + hash ^= hash_key_str(a->value.group_name, lttng_ht_seed); + break; + default: + abort(); } - for (i = 0; i < ids->count; i++) { - lttng_tracker_id_reset(&ids->id_array[i]); - } - free(ids->id_array); - free(ids); + return hash; } -int lttng_tracker_ids_serialize(const struct lttng_tracker_ids *ids, - struct lttng_dynamic_buffer *buffer) +LTTNG_HIDDEN +bool process_attr_tracker_value_equal(const struct process_attr_value *a, + const struct process_attr_value *b) { - int ret = 0; - int value; - const char *string = NULL; - unsigned int count; - enum lttng_tracker_id_status status; - const struct lttng_tracker_id *id; - unsigned int i; - - status = lttng_tracker_ids_get_count(ids, &count); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = LTTNG_ERR_INVALID; - goto error; + if (a->type != b->type) { + return false; } + switch (a->type) { + case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID: + return a->value.pid == b->value.pid; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID: + return a->value.uid == b->value.uid; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID: + return a->value.gid == b->value.gid; + case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME: + return !strcmp(a->value.user_name, b->value.user_name); + case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME: + return !strcmp(a->value.group_name, b->value.group_name); + default: + abort(); + } +} - for (i = 0; i < count; i++) { - struct lttcomm_tracker_id_header id_hdr; - size_t var_data_len = 0; - - id = lttng_tracker_ids_get_at_index(ids, i); - if (!id) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - - memset(&id_hdr, 0, sizeof(id_hdr)); - id_hdr.type = lttng_tracker_id_get_type(id); - switch (id_hdr.type) { - case LTTNG_ID_ALL: - break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_get_value(id, &value); - id_hdr.u.value = value; - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_get_string( - id, &string); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - - id_hdr.u.var_data_len = var_data_len = - strlen(string) + 1; - break; - default: - ret = -LTTNG_ERR_INVALID; - goto error; - } - ret = lttng_dynamic_buffer_append( - buffer, &id_hdr, sizeof(id_hdr)); - if (ret) { - ret = -LTTNG_ERR_NOMEM; - goto error; - } - ret = lttng_dynamic_buffer_append( - buffer, string, var_data_len); - if (ret) { - ret = -LTTNG_ERR_NOMEM; - goto error; - } +LTTNG_HIDDEN +void process_attr_value_destroy(struct process_attr_value *value) +{ + if (!value) { + return; } -error: - return ret; + if (is_value_type_name(value->type)) { + free(value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME ? + value->value.user_name : + value->value.group_name); + } + free(value); } diff --git a/src/common/tracker.h b/src/common/tracker.h new file mode 100644 index 000000000..933c5beeb --- /dev/null +++ b/src/common/tracker.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2019 Jonathan Rajotte + * Copyright (C) 2020 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_COMMON_TRACKER_H +#define LTTNG_COMMON_TRACKER_H + +#include +#include + +#include +#include +#include +#include + +struct process_attr_value { + enum lttng_process_attr_value_type type; + union value { + pid_t pid; + uid_t uid; + char *user_name; + gid_t gid; + char *group_name; + } value; +}; + +struct lttng_process_attr_values { + /* Array of struct process_attr_tracker_value. */ + struct lttng_dynamic_pointer_array array; +}; + +LTTNG_HIDDEN +const char *lttng_process_attr_to_string(enum lttng_process_attr process_attr); + +LTTNG_HIDDEN +struct lttng_process_attr_values *lttng_process_attr_values_create(void); + +/* Prefixed with '_' since the name conflicts with a public API. */ +LTTNG_HIDDEN +unsigned int _lttng_process_attr_values_get_count( + const struct lttng_process_attr_values *values); + +LTTNG_HIDDEN +const struct process_attr_value *lttng_process_attr_tracker_values_get_at_index( + const struct lttng_process_attr_values *values, + unsigned int index); + +LTTNG_HIDDEN +int lttng_process_attr_values_serialize( + const struct lttng_process_attr_values *values, + struct lttng_dynamic_buffer *buffer); + +LTTNG_HIDDEN +ssize_t lttng_process_attr_values_create_from_buffer( + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + const struct lttng_buffer_view *buffer_view, + struct lttng_process_attr_values **_values); + +LTTNG_HIDDEN +void lttng_process_attr_values_destroy( + struct lttng_process_attr_values *values); + +LTTNG_HIDDEN +struct process_attr_value *process_attr_value_copy( + const struct process_attr_value *value); + +LTTNG_HIDDEN +unsigned long process_attr_value_hash(const struct process_attr_value *a); + +LTTNG_HIDDEN +bool process_attr_tracker_value_equal(const struct process_attr_value *a, + const struct process_attr_value *b); + +LTTNG_HIDDEN +void process_attr_value_destroy(struct process_attr_value *value); + +LTTNG_HIDDEN +enum lttng_error_code process_attr_value_from_comm( + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + enum lttng_process_attr_value_type value_type, + const struct process_attr_integral_value_comm *integral_value, + const struct lttng_buffer_view *value_view, + struct process_attr_value **value); + +#endif /* LTTNG_COMMON_TRACKER_H */ diff --git a/src/common/utils.c b/src/common/utils.c index 646ebbbc7..d6c67bb0f 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -7,6 +7,7 @@ * */ +#include "common/macros.h" #define _LGPL_SOURCE #include #include @@ -50,6 +51,9 @@ #error MAX_NAME_LEN_SCANF_IS_A_BROKEN_API must be updated to match (PROC_MEMINFO_FIELD_MAX_NAME_LEN - 1) #endif +#define FALLBACK_USER_BUFLEN 16384 +#define FALLBACK_GROUP_BUFLEN 16384 + /* * Return a partial realpath(3) of the path even if the full path does not * exist. For instance, with /tmp/test1/test2/test3, if test2/ does not exist @@ -1528,3 +1532,134 @@ int utils_change_working_directory(const char *path) end: return ret; } + +LTTNG_HIDDEN +enum lttng_error_code utils_user_id_from_name(const char *user_name, uid_t *uid) +{ + struct passwd p, *pres; + int ret; + enum lttng_error_code ret_val = LTTNG_OK; + char *buf = NULL; + ssize_t buflen; + + buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen < 0) { + buflen = FALLBACK_USER_BUFLEN; + } + + buf = zmalloc(buflen); + if (!buf) { + ret_val = LTTNG_ERR_NOMEM; + goto end; + } + + for (;;) { + ret = getpwnam_r(user_name, &p, buf, buflen, &pres); + switch (ret) { + case EINTR: + continue; + case ERANGE: + buflen *= 2; + free(buf); + buf = zmalloc(buflen); + if (!buf) { + ret_val = LTTNG_ERR_NOMEM; + goto end; + } + continue; + default: + goto end_loop; + } + } +end_loop: + + switch (ret) { + case 0: + if (pres == NULL) { + ret_val = LTTNG_ERR_USER_NOT_FOUND; + } else { + *uid = p.pw_uid; + DBG("Lookup of tracker UID/VUID: name '%s' maps to uid %" PRId64, + user_name, (int64_t) *uid); + ret_val = LTTNG_OK; + } + break; + case ENOENT: + case ESRCH: + case EBADF: + case EPERM: + ret_val = LTTNG_ERR_USER_NOT_FOUND; + break; + default: + ret_val = LTTNG_ERR_NOMEM; + } +end: + free(buf); + return ret_val; +} + +LTTNG_HIDDEN +enum lttng_error_code utils_group_id_from_name( + const char *group_name, gid_t *gid) +{ + struct group g, *gres; + int ret; + enum lttng_error_code ret_val = LTTNG_OK; + char *buf = NULL; + ssize_t buflen; + + buflen = sysconf(_SC_GETGR_R_SIZE_MAX); + if (buflen < 0) { + buflen = FALLBACK_GROUP_BUFLEN; + } + + buf = zmalloc(buflen); + if (!buf) { + ret_val = LTTNG_ERR_NOMEM; + goto end; + } + + for (;;) { + ret = getgrnam_r(group_name, &g, buf, buflen, &gres); + switch (ret) { + case EINTR: + continue; + case ERANGE: + buflen *= 2; + free(buf); + buf = zmalloc(buflen); + if (!buf) { + ret_val = LTTNG_ERR_NOMEM; + goto end; + } + continue; + default: + goto end_loop; + } + } +end_loop: + + switch (ret) { + case 0: + if (gres == NULL) { + ret_val = LTTNG_ERR_GROUP_NOT_FOUND; + } else { + *gid = g.gr_gid; + DBG("Lookup of tracker GID/GUID: name '%s' maps to gid %" PRId64, + group_name, (int64_t) *gid); + ret_val = LTTNG_OK; + } + break; + case ENOENT: + case ESRCH: + case EBADF: + case EPERM: + ret_val = LTTNG_ERR_GROUP_NOT_FOUND; + break; + default: + ret_val = LTTNG_ERR_NOMEM; + } +end: + free(buf); + return ret_val; +} diff --git a/src/common/utils.h b/src/common/utils.h index b6e5c97db..dec4cd8aa 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -8,12 +8,12 @@ #ifndef _COMMON_UTILS_H #define _COMMON_UTILS_H -#include -#include -#include #include +#include #include +#include #include +#include #include @@ -54,5 +54,9 @@ int utils_show_help(int section, const char *page_name, const char *help_msg); int utils_get_memory_available(size_t *value); int utils_get_memory_total(size_t *value); int utils_change_working_directory(const char *path); +enum lttng_error_code utils_user_id_from_name( + const char *user_name, uid_t *user_id); +enum lttng_error_code utils_group_id_from_name( + const char *group_name, gid_t *group_id); #endif /* _COMMON_UTILS_H */ diff --git a/src/lib/lttng-ctl/Makefile.am b/src/lib/lttng-ctl/Makefile.am index de390175b..1bee05f0c 100644 --- a/src/lib/lttng-ctl/Makefile.am +++ b/src/lib/lttng-ctl/Makefile.am @@ -8,7 +8,8 @@ lib_LTLIBRARIES = liblttng-ctl.la liblttng_ctl_la_SOURCES = lttng-ctl.c snapshot.c lttng-ctl-helper.h \ lttng-ctl-health.c save.c load.c deprecated-symbols.c \ - channel.c rotate.c event.c destruction-handle.c clear.c + channel.c rotate.c event.c destruction-handle.c clear.c \ + tracker.c liblttng_ctl_la_LDFLAGS = \ $(LT_NO_UNDEFINED) diff --git a/src/lib/lttng-ctl/deprecated-symbols.c b/src/lib/lttng-ctl/deprecated-symbols.c index 90f639bee..0ea802c5e 100644 --- a/src/lib/lttng-ctl/deprecated-symbols.c +++ b/src/lib/lttng-ctl/deprecated-symbols.c @@ -16,3 +16,8 @@ size_t default_kernel_channel_subbuf_size; size_t default_metadata_subbuf_size; size_t default_ust_pid_channel_subbuf_size; size_t default_ust_uid_channel_subbuf_size; + +const char * const config_element_pid_tracker; +const char * const config_element_target_pid; +const char * const config_element_targets; +const char * const config_element_trackers; diff --git a/src/lib/lttng-ctl/lttng-ctl-helper.h b/src/lib/lttng-ctl/lttng-ctl-helper.h index 8c14e1fdc..f252bbbde 100644 --- a/src/lib/lttng-ctl/lttng-ctl-helper.h +++ b/src/lib/lttng-ctl/lttng-ctl-helper.h @@ -40,9 +40,11 @@ int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm, /* * Calls lttng_ctl_ask_sessiond_fds_varlen() with no expected command header. */ -static inline -int lttng_ctl_ask_sessiond_varlen_no_cmd_header(struct lttcomm_session_msg *lsm, - void *vardata, size_t vardata_len, void **user_payload_buf) +static inline int lttng_ctl_ask_sessiond_varlen_no_cmd_header( + struct lttcomm_session_msg *lsm, + const void *vardata, + size_t vardata_len, + void **user_payload_buf) { return lttng_ctl_ask_sessiond_fds_varlen(lsm, NULL, 0, vardata, vardata_len, user_payload_buf, NULL, NULL); diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 32ca4b267..7622a5137 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -22,21 +22,21 @@ #include #include #include +#include #include +#include #include #include -#include -#include -#include -#include -#include #include +#include +#include #include -#include -#include +#include +#include #include -#include -#include +#include +#include +#include #include "filter/filter-ast.h" #include "filter/filter-parser.h" @@ -2817,172 +2817,6 @@ end: return ret; } -/* - * List IDs in the tracker. - * - * tracker_type is the type of tracker. - * ids is set to an allocated array of IDs currently tracked. On - * success, ids and contained ids must be freed/destroy by the caller. - * nr_ids is set to the number of entries contained by the ids array. - * - * Returns 0 on success, else a negative LTTng error code. - */ -int lttng_list_tracker_ids(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - struct lttng_tracker_ids **_ids) -{ - int ret, i; - struct lttcomm_session_msg lsm; - struct lttcomm_tracker_command_header *cmd_header = NULL; - char *cmd_payload = NULL, *p; - size_t cmd_header_len; - size_t nr_ids = 0; - struct lttng_tracker_ids *ids = NULL; - - if (handle == NULL) { - return -LTTNG_ERR_INVALID; - } - - memset(&lsm, 0, sizeof(lsm)); - lsm.cmd_type = LTTNG_LIST_TRACKER_IDS; - lsm.u.id_tracker_list.tracker_type = tracker_type; - lttng_ctl_copy_string(lsm.session.name, handle->session_name, - sizeof(lsm.session.name)); - COPY_DOMAIN_PACKED(lsm.domain, handle->domain); - - ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, NULL, 0, NULL, 0, - (void **) &cmd_payload, (void **) &cmd_header, - &cmd_header_len); - if (ret < 0) { - goto error; - } - - /* Set number of tracker_id and free command header */ - nr_ids = cmd_header->nb_tracker_id; - if (nr_ids > INT_MAX) { - ret = -LTTNG_ERR_OVERFLOW; - goto error; - } - free(cmd_header); - cmd_header = NULL; - - ids = lttng_tracker_ids_create(nr_ids); - if (!ids) { - ret = -LTTNG_ERR_NOMEM; - goto error; - } - - p = cmd_payload; - for (i = 0; i < nr_ids; i++) { - struct lttcomm_tracker_id_header *tracker_id; - struct lttng_tracker_id *id; - enum lttng_tracker_id_status status; - - tracker_id = (struct lttcomm_tracker_id_header *) p; - p += sizeof(struct lttcomm_tracker_id_header); - id = lttng_tracker_ids_get_pointer_of_index(ids, i); - if (!id) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - - switch (tracker_id->type) { - case LTTNG_ID_ALL: - status = lttng_tracker_id_set_all(id); - break; - case LTTNG_ID_VALUE: - id->value = tracker_id->u.value; - status = lttng_tracker_id_set_value( - id, tracker_id->u.value); - break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_set_string(id, p); - p += tracker_id->u.var_data_len; - break; - default: - goto error; - } - - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - } - free(cmd_payload); - *_ids = ids; - return 0; - -error: - lttng_tracker_ids_destroy(ids); - free(cmd_payload); - free(cmd_header); - return ret; -} - -/* - * List PIDs in the tracker. - * - * enabled is set to whether the PID tracker is enabled. - * pids is set to an allocated array of PIDs currently tracked. On - * success, pids must be freed by the caller. - * nr_pids is set to the number of entries contained by the pids array. - * - * Returns 0 on success, else a negative LTTng error code. - */ -int lttng_list_tracker_pids(struct lttng_handle *handle, - int *_enabled, int32_t **_pids, size_t *_nr_pids) -{ - struct lttng_tracker_ids *ids = NULL; - unsigned int nr_ids = 0; - int *pids = NULL; - int ret = 0, i; - enum lttng_tracker_id_status status; - const struct lttng_tracker_id *id; - - ret = lttng_list_tracker_ids(handle, LTTNG_TRACKER_PID, &ids); - if (ret < 0) { - return ret; - } - - status = lttng_tracker_ids_get_count(ids, &nr_ids); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_INVALID; - goto end; - } - - if (nr_ids == 1) { - id = lttng_tracker_ids_get_at_index(ids, 0); - if (id && lttng_tracker_id_get_type(id) == LTTNG_ID_ALL) { - *_enabled = 0; - goto end; - } - } - - *_enabled = 1; - - pids = zmalloc(nr_ids * sizeof(*pids)); - if (!pids) { - ret = -LTTNG_ERR_NOMEM; - goto end; - } - for (i = 0; i < nr_ids; i++) { - id = lttng_tracker_ids_get_at_index(ids, i); - status = lttng_tracker_id_get_value(id, &pids[i]); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - ret = -LTTNG_ERR_UNK; - goto end; - } - } - *_pids = pids; - *_nr_pids = nr_ids; -end: - lttng_tracker_ids_destroy(ids); - if (ret < 0) { - free(pids); - } - return ret; -} - /* * Regenerate the metadata for a session. * Return 0 on success, a negative error code on error. @@ -3117,131 +2951,6 @@ end: return ret; } -static int lttng_track_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id, - enum lttcomm_sessiond_command cmd) -{ - int ret; - struct lttcomm_session_msg lsm; - const char *var_data = NULL; - size_t var_data_len = 0; - int value; - enum lttng_tracker_id_status status; - - /* NULL arguments are forbidden. No default values. */ - if (handle == NULL) { - goto error; - } - - memset(&lsm, 0, sizeof(lsm)); - - lsm.cmd_type = cmd; - lsm.u.id_tracker.tracker_type = tracker_type; - lsm.u.id_tracker.id_type = lttng_tracker_id_get_type(id); - switch (lsm.u.id_tracker.id_type) { - case LTTNG_ID_ALL: - break; - case LTTNG_ID_VALUE: - status = lttng_tracker_id_get_value(id, &value); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - goto error; - } - lsm.u.id_tracker.u.value = value; - break; - case LTTNG_ID_STRING: - status = lttng_tracker_id_get_string(id, &var_data); - if (status != LTTNG_TRACKER_ID_STATUS_OK) { - goto error; - } - var_data_len = strlen(var_data) + 1; /* Includes \0. */ - lsm.u.id_tracker.u.var_len = var_data_len; - break; - default: - goto error; - } - - COPY_DOMAIN_PACKED(lsm.domain, handle->domain); - - lttng_ctl_copy_string(lsm.session.name, handle->session_name, - sizeof(lsm.session.name)); - - ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( - &lsm, (char *) var_data, var_data_len, NULL); - return ret; -error: - return -LTTNG_ERR_INVALID; -} - -/* - * Add ID to session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_track_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id) -{ - return lttng_track_untrack_id(handle, tracker_type, id, LTTNG_TRACK_ID); -} - -/* - * Remove ID from session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_untrack_id(struct lttng_handle *handle, - enum lttng_tracker_type tracker_type, - const struct lttng_tracker_id *id) -{ - return lttng_track_untrack_id( - handle, tracker_type, id, LTTNG_UNTRACK_ID); -} - -/* - * Add PID to session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_track_pid(struct lttng_handle *handle, int pid) -{ - int ret; - struct lttng_tracker_id *id = NULL; - enum lttng_tracker_id_status status; - - id = lttng_tracker_id_create(); - status = lttng_tracker_id_set_value(id, pid); - if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - - ret = lttng_track_id(handle, LTTNG_TRACKER_PID, id); -error: - lttng_tracker_id_destroy(id); - return ret; -} - -/* - * Remove PID from session tracker. - * Return 0 on success else a negative LTTng error code. - */ -int lttng_untrack_pid(struct lttng_handle *handle, int pid) -{ - int ret; - struct lttng_tracker_id *id = NULL; - enum lttng_tracker_id_status status; - - id = lttng_tracker_id_create(); - status = lttng_tracker_id_set_value(id, pid); - if (status == LTTNG_TRACKER_ID_STATUS_INVALID) { - ret = -LTTNG_ERR_INVALID; - goto error; - } - - ret = lttng_untrack_id(handle, LTTNG_TRACKER_PID, id); -error: - lttng_tracker_id_destroy(id); - return ret; -} - /* * lib constructor. */ diff --git a/src/lib/lttng-ctl/tracker.c b/src/lib/lttng-ctl/tracker.c new file mode 100644 index 000000000..3f852fe72 --- /dev/null +++ b/src/lib/lttng-ctl/tracker.c @@ -0,0 +1,757 @@ +/* + * Copyright (C) 2020 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include "lttng-ctl-helper.h" +#include "lttng/domain.h" +#include "lttng/lttng-error.h" +#include +#include +#include + +struct lttng_process_attr_tracker_handle { + char *session_name; + enum lttng_domain_type domain; + enum lttng_process_attr process_attr; + struct lttng_process_attr_values *inclusion_set; +}; + +void lttng_process_attr_tracker_handle_destroy( + struct lttng_process_attr_tracker_handle *tracker) +{ + if (!tracker) { + return; + } + + lttng_process_attr_values_destroy(tracker->inclusion_set); + free(tracker->session_name); + free(tracker); +} + +enum lttng_error_code lttng_session_get_tracker_handle(const char *session_name, + enum lttng_domain_type domain, + enum lttng_process_attr process_attr, + struct lttng_process_attr_tracker_handle **out_tracker_handle) +{ + enum lttng_error_code ret_code = LTTNG_OK; + struct lttng_process_attr_tracker_handle *handle = NULL; + enum lttng_process_attr_tracker_handle_status status; + enum lttng_tracking_policy policy; + + if (!session_name || !out_tracker_handle) { + ret_code = LTTNG_ERR_INVALID; + goto error; + } + + if (domain != LTTNG_DOMAIN_KERNEL && domain != LTTNG_DOMAIN_UST) { + ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN; + goto error; + } + + handle = zmalloc(sizeof(*handle)); + if (!handle) { + ret_code = LTTNG_ERR_NOMEM; + goto error; + } + + handle->session_name = strdup(session_name); + if (!handle->session_name) { + ret_code = LTTNG_ERR_NOMEM; + goto error; + } + + handle->domain = domain; + handle->process_attr = process_attr; + + /* + * Use the `get_tracking_policy` command to validate the tracker's + * existance. + */ + status = lttng_process_attr_tracker_handle_get_tracking_policy( + handle, &policy); + switch (status) { + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: + break; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST: + ret_code = LTTNG_ERR_SESSION_NOT_EXIST; + goto error; + default: + ret_code = LTTNG_ERR_UNK; + goto error; + } + + *out_tracker_handle = handle; + return ret_code; +error: + lttng_process_attr_tracker_handle_destroy(handle); + return ret_code; +} + +enum lttng_process_attr_tracker_handle_status +lttng_process_attr_tracker_handle_get_tracking_policy( + const struct lttng_process_attr_tracker_handle *tracker, + enum lttng_tracking_policy *policy) +{ + void *reply = NULL; + int reply_ret; + enum lttng_process_attr_tracker_handle_status status = + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; + struct lttcomm_session_msg lsm = { + .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY, + }; + + if (!tracker || !policy) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; + goto end; + } + + lttng_ctl_copy_string(lsm.session.name, tracker->session_name, + sizeof(lsm.session.name)); + lsm.domain.type = tracker->domain; + lsm.u.process_attr_tracker_get_tracking_policy.process_attr = + (int32_t) tracker->process_attr; + + /* Command returns a session descriptor on success. */ + reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( + &lsm, NULL, 0, &reply); + if (reply_ret != sizeof(uint32_t)) { + if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST || + reply_ret == -LTTNG_ERR_SESS_NOT_FOUND) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST; + } else { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; + } + goto end; + } + + *policy = (enum lttng_tracking_policy)(*((const uint32_t *) reply)); +end: + free(reply); + return status; +} + +enum lttng_process_attr_tracker_handle_status +lttng_process_attr_tracker_handle_set_tracking_policy( + const struct lttng_process_attr_tracker_handle *tracker, + enum lttng_tracking_policy policy) +{ + int reply_ret; + enum lttng_process_attr_tracker_handle_status status = + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; + struct lttcomm_session_msg lsm = { + .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY, + }; + + if (!tracker) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; + goto end; + } + + lttng_ctl_copy_string(lsm.session.name, tracker->session_name, + sizeof(lsm.session.name)); + lsm.domain.type = tracker->domain; + lsm.u.process_attr_tracker_set_tracking_policy.process_attr = + (int32_t) tracker->process_attr; + lsm.u.process_attr_tracker_set_tracking_policy.tracking_policy = + (int32_t) policy; + + /* Command returns a session descriptor on success. */ + reply_ret = lttng_ctl_ask_sessiond(&lsm, NULL); + if (reply_ret < 0) { + if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST; + } else { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; + } + goto end; + } +end: + return status; +} + +#define DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(command_upper, \ + command_lower, process_attr_name, value_type_name, \ + value_type_c, value_type_enum) \ + enum lttng_process_attr_tracker_handle_status \ + lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \ + const struct lttng_process_attr_tracker_handle \ + *tracker, \ + value_type_c value) \ + { \ + int ret; \ + enum lttng_process_attr_tracker_handle_status status = \ + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \ + struct lttcomm_session_msg lsm = { \ + .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \ + \ + if (!tracker) { \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \ + goto end; \ + } \ + \ + lttng_ctl_copy_string(lsm.session.name, tracker->session_name, \ + sizeof(lsm.session.name)); \ + lsm.domain.type = tracker->domain; \ + lsm.u.process_attr_tracker_add_remove_include_value \ + .process_attr = \ + (int32_t) tracker->process_attr; \ + lsm.u.process_attr_tracker_add_remove_include_value \ + .value_type = (uint32_t) \ + LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \ + \ + if (is_signed(value_type_c)) { \ + lsm.u.process_attr_tracker_add_remove_include_value \ + .integral_value.u._signed = value; \ + } else { \ + lsm.u.process_attr_tracker_add_remove_include_value \ + .integral_value.u._unsigned = value; \ + } \ + \ + ret = lttng_ctl_ask_sessiond(&lsm, NULL); \ + if (ret < 0) { \ + switch (-ret) { \ + case LTTNG_ERR_PROCESS_ATTR_EXISTS: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \ + break; \ + case LTTNG_ERR_PROCESS_ATTR_MISSING: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \ + break; \ + case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \ + break; \ + default: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \ + } \ + } \ + end: \ + return status; \ + } + +#define DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(command_upper, \ + command_lower, process_attr_name, value_type_name, \ + value_type_enum) \ + enum lttng_process_attr_tracker_handle_status \ + lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \ + const struct lttng_process_attr_tracker_handle \ + *tracker, \ + const char *value) \ + { \ + int ret; \ + enum lttng_process_attr_tracker_handle_status status = \ + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \ + struct lttcomm_session_msg lsm = { \ + .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE}; \ + const size_t len = value ? strlen(value) + 1 : 0; \ + \ + if (!tracker || !value) { \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \ + goto end; \ + } \ + \ + lttng_ctl_copy_string(lsm.session.name, tracker->session_name, \ + sizeof(lsm.session.name)); \ + lsm.domain.type = tracker->domain; \ + lsm.u.process_attr_tracker_add_remove_include_value \ + .process_attr = \ + (int32_t) tracker->process_attr; \ + lsm.u.process_attr_tracker_add_remove_include_value.name_len = \ + (uint32_t) len; \ + lsm.u.process_attr_tracker_add_remove_include_value \ + .value_type = (uint32_t) \ + LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \ + \ + ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( \ + &lsm, value, len, NULL); \ + if (ret < 0) { \ + switch (-ret) { \ + case LTTNG_ERR_PROCESS_ATTR_EXISTS: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \ + break; \ + case LTTNG_ERR_PROCESS_ATTR_MISSING: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \ + break; \ + case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \ + break; \ + case LTTNG_ERR_USER_NOT_FOUND: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND; \ + break; \ + case LTTNG_ERR_GROUP_NOT_FOUND: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND; \ + break; \ + default: \ + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \ + } \ + } \ + end: \ + return status; \ + } + +/* PID */ +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + ADD, add, process_id, pid, pid_t, PID); +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + REMOVE, remove, process_id, pid, pid_t, PID); + +/* VPID */ +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + ADD, add, virtual_process_id, pid, pid_t, PID); +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + REMOVE, remove, virtual_process_id, pid, pid_t, PID); + +/* UID */ +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + ADD, add, user_id, uid, uid_t, UID); +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + REMOVE, remove, user_id, uid, uid_t, UID); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + ADD, add, user_id, user_name, USER_NAME); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + REMOVE, remove, user_id, user_name, USER_NAME); + +/* VUID */ +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + ADD, add, virtual_user_id, uid, uid_t, UID); +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + REMOVE, remove, virtual_user_id, uid, uid_t, UID); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + ADD, add, virtual_user_id, user_name, USER_NAME); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + REMOVE, remove, virtual_user_id, user_name, USER_NAME); + +/* GID */ +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + ADD, add, group_id, gid, gid_t, GID); +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + REMOVE, remove, group_id, gid, gid_t, GID); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + ADD, add, group_id, group_name, GROUP_NAME); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + REMOVE, remove, group_id, group_name, GROUP_NAME); + +/* VGID */ +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + ADD, add, virtual_group_id, gid, gid_t, GID); +DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC( + REMOVE, remove, virtual_group_id, gid, gid_t, GID); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + ADD, add, virtual_group_id, group_name, GROUP_NAME); +DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC( + REMOVE, remove, virtual_group_id, group_name, GROUP_NAME); + +enum lttng_process_attr_tracker_handle_status +lttng_process_attr_tracker_handle_get_inclusion_set( + struct lttng_process_attr_tracker_handle *tracker, + const struct lttng_process_attr_values **values) +{ + void *reply = NULL; + int reply_ret; + enum lttng_process_attr_tracker_handle_status status = + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; + struct lttcomm_session_msg lsm = { + .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET, + }; + struct lttng_buffer_view inclusion_set_view; + ssize_t inclusion_set_ret; + + if (!tracker || !values) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; + goto end; + } + + lttng_process_attr_values_destroy(tracker->inclusion_set); + tracker->inclusion_set = NULL; + + lttng_ctl_copy_string(lsm.session.name, tracker->session_name, + sizeof(lsm.session.name)); + lsm.domain.type = tracker->domain; + lsm.u.process_attr_tracker_get_tracking_policy.process_attr = + (int32_t) tracker->process_attr; + + /* Command returns a session descriptor on success. */ + reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( + &lsm, NULL, 0, &reply); + if (reply_ret < 0) { + if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST; + } else if (reply_ret == + -LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; + } else { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; + } + goto end; + } else if (reply_ret == 0) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR; + goto end; + } + + inclusion_set_view = lttng_buffer_view_init(reply, 0, reply_ret); + if (!inclusion_set_view.data) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR; + goto end; + } + + inclusion_set_ret = lttng_process_attr_values_create_from_buffer( + tracker->domain, tracker->process_attr, + &inclusion_set_view, &tracker->inclusion_set); + if (inclusion_set_ret < 0) { + status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR; + goto end; + } + *values = tracker->inclusion_set; +end: + free(reply); + return status; +} + +enum lttng_process_attr_values_status lttng_process_attr_values_get_count( + const struct lttng_process_attr_values *values, + unsigned int *count) +{ + enum lttng_process_attr_values_status status = + LTTNG_PROCESS_ATTR_VALUES_STATUS_OK; + + if (!values || !count) { + status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; + goto end; + } + + *count = _lttng_process_attr_values_get_count(values); +end: + return status; +} + +enum lttng_process_attr_value_type lttng_process_attr_values_get_type_at_index( + const struct lttng_process_attr_values *values, + unsigned int index) +{ + enum lttng_process_attr_value_type type; + const struct process_attr_value *value; + + if (!values) { + type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID; + goto end; + } + + if (_lttng_process_attr_values_get_count(values) <= index) { + type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID; + goto end; + } + + value = lttng_process_attr_tracker_values_get_at_index(values, index); + type = value->type; +end: + return type; +} + +#define DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER( \ + value_type_name, value_type, expected_value_type) \ + enum lttng_process_attr_values_status \ + lttng_process_attr_values_get_##value_type_name##_at_index( \ + const struct lttng_process_attr_values \ + *values, \ + unsigned int index, \ + value_type *out_value) \ + { \ + enum lttng_process_attr_values_status status = \ + LTTNG_PROCESS_ATTR_VALUES_STATUS_OK; \ + const struct process_attr_value *value; \ + \ + if (!values) { \ + status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \ + goto end; \ + } \ + \ + if (_lttng_process_attr_values_get_count(values) <= index) { \ + status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \ + goto end; \ + } \ + \ + value = lttng_process_attr_tracker_values_get_at_index( \ + values, index); \ + if (value->type != \ + LTTNG_PROCESS_ATTR_VALUE_TYPE_##expected_value_type) { \ + status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE; \ + goto end; \ + } \ + *out_value = value->value.value_type_name; \ + end: \ + return status; \ + } + +DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(pid, pid_t, PID); +DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(uid, uid_t, UID); +DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(gid, gid_t, GID); +DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(user_name, const char *, USER_NAME); +DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(group_name, const char *, GROUP_NAME); + +static enum lttng_error_code handle_status_to_error_code( + enum lttng_process_attr_tracker_handle_status handle_status) +{ + switch (handle_status) { + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY: + return LTTNG_ERR_INVALID; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST: + return LTTNG_ERR_SESSION_NOT_EXIST; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR: + return LTTNG_ERR_INVALID_PROTOCOL; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS: + return LTTNG_ERR_PID_TRACKED; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING: + return LTTNG_ERR_PID_NOT_TRACKED; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK: + return LTTNG_OK; + case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR: + default: + /* fall-through. */ + return LTTNG_ERR_UNK; + } +} + +/* + * Add PID to session tracker. + * Return 0 on success else a negative LTTng error code. + */ +int lttng_track_pid(struct lttng_handle *handle, int pid) +{ + enum lttng_error_code ret_code; + struct lttng_process_attr_tracker_handle *tracker_handle = NULL; + enum lttng_process_attr_tracker_handle_status handle_status; + enum lttng_tracking_policy policy; + enum lttng_process_attr process_attr; + + if (!handle) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ? + LTTNG_PROCESS_ATTR_PROCESS_ID : + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID; + + ret_code = lttng_session_get_tracker_handle(handle->session_name, + handle->domain.type, + process_attr, &tracker_handle); + if (ret_code != LTTNG_OK) { + goto end; + } + + if (pid == -1) { + handle_status = lttng_process_attr_tracker_handle_set_tracking_policy( + tracker_handle, + LTTNG_TRACKING_POLICY_INCLUDE_ALL); + ret_code = handle_status_to_error_code(handle_status); + goto end; + } + + handle_status = lttng_process_attr_tracker_handle_get_tracking_policy( + tracker_handle, &policy); + if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + ret_code = handle_status_to_error_code(handle_status); + goto end; + } + + if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) { + handle_status = lttng_process_attr_tracker_handle_set_tracking_policy( + tracker_handle, + LTTNG_TRACKING_POLICY_INCLUDE_SET); + if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + ret_code = handle_status_to_error_code(handle_status); + goto end; + } + } + + handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ? + lttng_process_attr_process_id_tracker_handle_add_pid( + tracker_handle, + (pid_t) pid) : + lttng_process_attr_virtual_process_id_tracker_handle_add_pid( + tracker_handle, + (pid_t) pid); + ret_code = handle_status_to_error_code(handle_status); +end: + return ret_code == LTTNG_OK ? 0 : -ret_code; +} + +/* + * Remove PID from session tracker. + * Return 0 on success else a negative LTTng error code. + */ +int lttng_untrack_pid(struct lttng_handle *handle, int pid) +{ + enum lttng_error_code ret_code; + struct lttng_process_attr_tracker_handle *tracker_handle = NULL; + enum lttng_process_attr_tracker_handle_status handle_status; + enum lttng_tracking_policy policy; + enum lttng_process_attr process_attr; + + if (!handle) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ? + LTTNG_PROCESS_ATTR_PROCESS_ID : + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID; + ret_code = lttng_session_get_tracker_handle(handle->session_name, + handle->domain.type, process_attr, &tracker_handle); + if (ret_code != LTTNG_OK) { + goto end; + } + + if (pid == -1) { + handle_status = lttng_process_attr_tracker_handle_set_tracking_policy( + tracker_handle, + LTTNG_TRACKING_POLICY_EXCLUDE_ALL); + ret_code = handle_status_to_error_code(handle_status); + goto end; + } + + handle_status = lttng_process_attr_tracker_handle_get_tracking_policy( + tracker_handle, &policy); + if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + ret_code = handle_status_to_error_code(handle_status); + goto end; + } + + if (policy == LTTNG_TRACKING_POLICY_EXCLUDE_ALL) { + ret_code = LTTNG_ERR_PID_NOT_TRACKED; + goto end; + } else if (policy == LTTNG_TRACKING_POLICY_INCLUDE_ALL) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ? + lttng_process_attr_process_id_tracker_handle_remove_pid( + tracker_handle, + (pid_t) pid) : + lttng_process_attr_virtual_process_id_tracker_handle_remove_pid( + tracker_handle, + (pid_t) pid); + if (handle_status == LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) { + ret_code = LTTNG_ERR_PID_NOT_TRACKED; + } +end: + return ret_code == LTTNG_OK ? 0 : -ret_code; +} + +/* + * List PIDs in the tracker. + * + * enabled is set to whether the PID tracker is enabled. + * pids is set to an allocated array of PIDs currently tracked. On + * success, pids must be freed by the caller. + * nr_pids is set to the number of entries contained by the pids array. + * + * Returns 0 on success, else a negative LTTng error code. + */ +int lttng_list_tracker_pids(struct lttng_handle *handle, + int *_enabled, + int32_t **_pids, + size_t *_nr_pids) +{ + enum lttng_error_code ret_code; + struct lttng_process_attr_tracker_handle *tracker_handle = NULL; + enum lttng_process_attr_tracker_handle_status handle_status; + const struct lttng_process_attr_values *values; + enum lttng_tracking_policy policy; + unsigned int pid_count, i; + int32_t *pid_array = NULL; + + if (!handle || !_enabled || !_pids || !_nr_pids) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + ret_code = lttng_session_get_tracker_handle(handle->session_name, + handle->domain.type, + LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID, &tracker_handle); + if (ret_code != LTTNG_OK) { + goto end; + } + + while (true) { + handle_status = lttng_process_attr_tracker_handle_get_inclusion_set( + tracker_handle, &values); + if (handle_status == + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + policy = LTTNG_TRACKING_POLICY_INCLUDE_SET; + break; + } else if (handle_status != + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) { + ret_code = handle_status_to_error_code(handle_status); + goto end; + } + + handle_status = lttng_process_attr_tracker_handle_get_tracking_policy( + tracker_handle, &policy); + if (handle_status != + LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) { + ret_code = handle_status_to_error_code(handle_status); + goto end; + } + + /* Tracking policy changed in the meantime, retry. */ + if (policy == LTTNG_TRACKING_POLICY_INCLUDE_SET) { + continue; + } + break; + } + + switch (policy) { + case LTTNG_TRACKING_POLICY_INCLUDE_ALL: + *_enabled = 0; + goto end; + case LTTNG_TRACKING_POLICY_EXCLUDE_ALL: + *_enabled = 1; + pid_count = 0; + break; + case LTTNG_TRACKING_POLICY_INCLUDE_SET: + { + const enum lttng_process_attr_values_status values_status = + lttng_process_attr_values_get_count( + values, &pid_count); + + if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) { + ret_code = LTTNG_ERR_UNK; + goto end; + } + break; + } + default: + ret_code = LTTNG_ERR_INVALID_PROTOCOL; + goto end; + } + + pid_array = zmalloc(pid_count * sizeof(int32_t)); + if (!pid_array) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + /* Extract values to a raw array. */ + for (i = 0; i < pid_count; i++) { + pid_t pid; + const enum lttng_process_attr_values_status values_status = + lttng_process_attr_values_get_pid_at_index( + values, i, &pid); + + if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) { + ret_code = LTTNG_ERR_UNK; + goto end; + } + pid_array[i] = (int32_t) pid; + } + *_nr_pids = (size_t) pid_count; + *_pids = pid_array; + pid_array = NULL; +end: + lttng_process_attr_tracker_handle_destroy(tracker_handle); + free(pid_array); + return ret_code == LTTNG_OK ? 0 : -ret_code; +} diff --git a/tests/regression/tools/mi/test_mi b/tests/regression/tools/mi/test_mi index ae122251b..af7ca7658 100755 --- a/tests/regression/tools/mi/test_mi +++ b/tests/regression/tools/mi/test_mi @@ -39,8 +39,8 @@ XPATH_LIST_UST_EVENT="$XPATH_CMD_OUTPUT/lttng:domains/lttng:domain[./lttng:type XPATH_SNAPSHOT_ADD_SNAPSHOT="$XPATH_CMD_OUTPUT/lttng:snapshot_action[./lttng:name = 'add-output']/lttng:output" XPATH_SNAPSHOT_LIST="$XPATH_CMD_OUTPUT/lttng:snapshot_action[./lttng:name = 'list-output']/lttng:output" XPATH_SNAPSHOT_DEL="$XPATH_CMD_OUTPUT/lttng:snapshot_action[./lttng:name = 'del-output']/lttng:output" -XPATH_TRACK_UNTRACK_VPID="$XPATH_CMD_OUTPUT/lttng:trackers/lttng:vpid_tracker/lttng:targets/lttng:vpid_target/lttng:type" -XPATH_VPID_TRACKER="$XPATH_CMD_OUTPUT/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vpid_tracker" +XPATH_TRACK_UNTRACK_VPID="$XPATH_CMD_OUTPUT/lttng:process_attr_trackers/lttng:vpid_process_attr_tracker/lttng:process_attr_values/lttng:vpid/lttng:type" +XPATH_VPID_TRACKER="$XPATH_CMD_OUTPUT/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:process_attr_trackers/lttng:vpid_process_attr_tracker" DEVNULL=/dev/null 2>&1 @@ -766,7 +766,7 @@ function test_track_untrack () ok $? "Mi test: session list with pid_tracker validate" #Check the good count - extract_xml $OUTPUT_DEST $XPATH_VPID_TRACKER"/lttng:targets/lttng:vpid_target/lttng:type/lttng:id" result + extract_xml $OUTPUT_DEST $XPATH_VPID_TRACKER"/lttng:process_attr_values/lttng:vpid/lttng:type/lttng:id" result num=$(echo "$result" | wc -l) test "$num" -eq "3" ok $? "Mi test: tracker pid listing expecting 3 target got $num" diff --git a/tests/regression/tools/save-load/load-42-trackers.lttng b/tests/regression/tools/save-load/load-42-trackers.lttng index 2848f3209..39b32f872 100644 --- a/tests/regression/tools/save-load/load-42-trackers.lttng +++ b/tests/regression/tools/save-load/load-42-trackers.lttng @@ -31,36 +31,36 @@ - - - - + + + + 666 - - - - - - + + + + + + 777 - - - - - - + + + + + + 888 - - - - - - - 999 - - - - + + + + + + + 999 + + + + false diff --git a/tests/regression/tools/save-load/test_load b/tests/regression/tools/save-load/test_load index b1ec57cf9..db54a177a 100755 --- a/tests/regression/tools/save-load/test_load +++ b/tests/regression/tools/save-load/test_load @@ -129,21 +129,21 @@ function test_trackers() break; fi $TESTDIR/../src/bin/lttng/$LTTNG_BIN --mi XML list "$SESSION_NAME-trackers" > $mi_output_file - mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vpid_tracker/lttng:targets/lttng:vpid_target") + mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:process_attr_trackers/lttng:vpid_process_attr_tracker/lttng:process_attr_values/lttng:vpid") if [[ $mi_result = "true" ]]; then ok 0 "VPID target is present" else fail "VPID target missing" fi - mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vuid_tracker/lttng:targets/lttng:vuid_target") + mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:process_attr_trackers/lttng:vuid_process_attr_tracker/lttng:process_attr_values/lttng:vuid") if [[ $mi_result = "true" ]]; then ok 0 "VUID target is present" else fail "VUID target missing" fi - mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:trackers/lttng:vgid_tracker/lttng:targets/lttng:vgid_target") + mi_result=$($CURDIR/../mi/extract_xml -e $mi_output_file "//lttng:command/lttng:output/lttng:sessions/lttng:session/lttng:domains/lttng:domain/lttng:process_attr_trackers/lttng:vgid_process_attr_tracker/lttng:process_attr_values/lttng:vgid") if [[ $mi_result = "true" ]]; then ok 0 "VGID target is present" else -- 2.34.1